diff options
89 files changed, 3838 insertions, 860 deletions
diff --git a/alpine/APKBUILD.in b/alpine/APKBUILD.in index e0b00f9782..60753c1227 100644 --- a/alpine/APKBUILD.in +++ b/alpine/APKBUILD.in @@ -13,13 +13,13 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl c-ares c-ares-dev ca-certificates cryptsetup-libs curl device-mapper-libs expat fakeroot flex fortify-headers gdbm git gmp isl json-c-dev kmod lddtree libacl libatomic libattr - libblkid libburn libbz2 libc-dev libcap libcurl libedit libffi libgcc + libblkid libburn libbz2 libc-dev libcap-dev libcurl libedit libffi libgcc libgomp libisoburn libisofs libltdl libressl libssh2 libstdc++ libtool libuuid libyang-dev linux-headers lzip lzo m4 make mkinitfs mpc1 mpfr3 mtools musl-dev ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre perl pkgconf python2 python2-dev readline readline-dev sqlite-libs squashfs-tools sudo tar texinfo xorriso xz-libs - py-sphinx rtrlib rtrlib-dev" + py-pip py-sphinx rtrlib rtrlib-dev" checkdepends="pytest py-setuptools" install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall" subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg" diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 5663ce54cb..f8ee66e2c8 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -516,7 +516,7 @@ DEFPY(bfd_show_peers, bfd_show_peers_cmd, "show bfd [vrf <NAME>] peers [json]", } DEFPY(bfd_show_peer, bfd_show_peer_cmd, - "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]", + "show bfd [vrf <NAME$vrf_name>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]", SHOW_STR "Bidirection Forwarding Detection\n" VRF_CMD_HELP_STR @@ -528,7 +528,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd, /* Look up the BFD peer. */ bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str, - ifname, vrfname); + ifname, vrf_name); if (bs == NULL) return CMD_WARNING_CONFIG_FAILED; @@ -543,7 +543,7 @@ DEFPY(bfd_show_peer, bfd_show_peer_cmd, } DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd, - "show bfd [vrf <NAME$vrfname>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]", + "show bfd [vrf <NAME$vrf_name>] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> counters [json]", SHOW_STR "Bidirection Forwarding Detection\n" VRF_CMD_HELP_STR @@ -564,7 +564,7 @@ DEFPY(bfd_show_peer_counters, bfd_show_peer_counters_cmd, /* Look up the BFD peer. */ bs = _find_peer_or_error(vty, argc, argv, label, peer_str, local_str, - ifname, vrfname); + ifname, vrf_name); if (bs == NULL) return CMD_WARNING_CONFIG_FAILED; diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index f5652b07c5..6caeb7ca1f 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -2114,15 +2114,12 @@ static void *bgp_aggr_aspath_hash_alloc(void *p) static void bgp_aggr_aspath_prepare(struct hash_backet *hb, void *arg) { - struct aspath *asmerge = NULL; struct aspath *hb_aspath = hb->data; struct aspath **aggr_aspath = arg; - if (*aggr_aspath) { - asmerge = aspath_aggregate(*aggr_aspath, hb_aspath); - aspath_free(*aggr_aspath); - *aggr_aspath = asmerge; - } else + if (*aggr_aspath) + *aggr_aspath = aspath_aggregate(*aggr_aspath, hb_aspath); + else *aggr_aspath = aspath_dup(hb_aspath); } @@ -2136,6 +2133,15 @@ void bgp_aggr_aspath_remove(void *arg) void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate, struct aspath *aspath) { + bgp_compute_aggregate_aspath_hash(aggregate, aspath); + + bgp_compute_aggregate_aspath_val(aggregate); + +} + +void bgp_compute_aggregate_aspath_hash(struct bgp_aggregate *aggregate, + struct aspath *aspath) +{ struct aspath *aggr_aspath = NULL; if ((aggregate == NULL) || (aspath == NULL)) @@ -2154,17 +2160,29 @@ void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate, */ aggr_aspath = hash_get(aggregate->aspath_hash, aspath, bgp_aggr_aspath_hash_alloc); + } - /* Compute aggregate's as-path. - */ + /* Increment reference counter. + */ + aggr_aspath->refcnt++; +} + +void bgp_compute_aggregate_aspath_val(struct bgp_aggregate *aggregate) +{ + if (aggregate == NULL) + return; + /* Re-compute aggregate's as-path. + */ + if (aggregate->aspath) { + aspath_free(aggregate->aspath); + aggregate->aspath = NULL; + } + if (aggregate->aspath_hash + && aggregate->aspath_hash->count) { hash_iterate(aggregate->aspath_hash, bgp_aggr_aspath_prepare, &aggregate->aspath); } - - /* Increment refernce counter. - */ - aggr_aspath->refcnt++; } void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate, @@ -2173,10 +2191,9 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate, struct aspath *aggr_aspath = NULL; struct aspath *ret_aspath = NULL; - if ((aggregate == NULL) || (aspath == NULL)) - return; - - if (aggregate->aspath_hash == NULL) + if ((!aggregate) + || (!aggregate->aspath_hash) + || (!aspath)) return; /* Look-up the aspath in the hash. @@ -2189,17 +2206,41 @@ void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate, ret_aspath = hash_release(aggregate->aspath_hash, aggr_aspath); aspath_free(ret_aspath); + ret_aspath = NULL; /* Remove aggregate's old as-path. */ aspath_free(aggregate->aspath); aggregate->aspath = NULL; - /* Compute aggregate's as-path. - */ - hash_iterate(aggregate->aspath_hash, - bgp_aggr_aspath_prepare, - &aggregate->aspath); + bgp_compute_aggregate_aspath_val(aggregate); } } } + +void bgp_remove_aspath_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct aspath *aspath) +{ + struct aspath *aggr_aspath = NULL; + struct aspath *ret_aspath = NULL; + + if ((!aggregate) + || (!aggregate->aspath_hash) + || (!aspath)) + return; + + /* Look-up the aspath in the hash. + */ + aggr_aspath = bgp_aggr_aspath_lookup(aggregate, aspath); + if (aggr_aspath) { + aggr_aspath->refcnt--; + + if (aggr_aspath->refcnt == 0) { + ret_aspath = hash_release(aggregate->aspath_hash, + aggr_aspath); + aspath_free(ret_aspath); + ret_aspath = NULL; + } + } +} + diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index f84b3740c9..10f6ee2821 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -134,8 +134,16 @@ extern uint8_t *aspath_snmp_pathseg(struct aspath *, size_t *); extern void bgp_compute_aggregate_aspath(struct bgp_aggregate *aggregate, struct aspath *aspath); + +extern void bgp_compute_aggregate_aspath_hash(struct bgp_aggregate *aggregate, + struct aspath *aspath); +extern void bgp_compute_aggregate_aspath_val(struct bgp_aggregate *aggregate); extern void bgp_remove_aspath_from_aggregate(struct bgp_aggregate *aggregate, struct aspath *aspath); +extern void bgp_remove_aspath_from_aggregate_hash( + struct bgp_aggregate *aggregate, + struct aspath *aspath); + extern void bgp_aggr_aspath_remove(void *arg); #endif /* _QUAGGA_BGP_ASPATH_H */ diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 248bbca8cf..a7cd3fee88 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -1305,14 +1305,20 @@ bgp_attr_nexthop_valid(struct peer *peer, struct attr *attr) if ((IPV4_NET0(nexthop_h) || IPV4_NET127(nexthop_h) || IPV4_CLASS_DE(nexthop_h)) && !BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) { + uint8_t data[7]; /* type(2) + length(1) + nhop(4) */ char buf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &attr->nexthop.s_addr, buf, INET_ADDRSTRLEN); flog_err(EC_BGP_ATTR_MARTIAN_NH, "Martian nexthop %s", buf); - bgp_notify_send(peer, BGP_NOTIFY_UPDATE_ERR, - BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP); + data[0] = BGP_ATTR_FLAG_TRANS; + data[1] = BGP_ATTR_NEXT_HOP; + data[2] = BGP_ATTR_NHLEN_IPV4; + memcpy(&data[3], &attr->nexthop.s_addr, BGP_ATTR_NHLEN_IPV4); + bgp_notify_send_with_data(peer, BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, + data, 7); return BGP_ATTR_PARSE_ERROR; } diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index 22d61f702d..432c922ea5 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -910,15 +910,13 @@ static void *bgp_aggr_communty_hash_alloc(void *p) static void bgp_aggr_community_prepare(struct hash_backet *hb, void *arg) { - struct community *commerge = NULL; struct community *hb_community = hb->data; struct community **aggr_community = arg; - if (*aggr_community) { - commerge = community_merge(*aggr_community, hb_community); - *aggr_community = community_uniq_sort(commerge); - community_free(&commerge); - } else + if (*aggr_community) + *aggr_community = community_merge(*aggr_community, + hb_community); + else *aggr_community = community_dup(hb_community); } @@ -932,6 +930,14 @@ void bgp_aggr_community_remove(void *arg) void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate, struct community *community) { + bgp_compute_aggregate_community_hash(aggregate, community); + bgp_compute_aggregate_community_val(aggregate); +} + + +void bgp_compute_aggregate_community_hash(struct bgp_aggregate *aggregate, + struct community *community) +{ struct community *aggr_community = NULL; if ((aggregate == NULL) || (community == NULL)) @@ -951,32 +957,47 @@ void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate, */ aggr_community = hash_get(aggregate->community_hash, community, bgp_aggr_communty_hash_alloc); + } - /* Re-compute aggregate's community. - */ - if (aggregate->community) - community_free(&aggregate->community); + /* Increment reference counter. + */ + aggr_community->refcnt++; +} +void bgp_compute_aggregate_community_val(struct bgp_aggregate *aggregate) +{ + struct community *commerge = NULL; + + if (aggregate == NULL) + return; + + /* Re-compute aggregate's community. + */ + if (aggregate->community) + community_free(&aggregate->community); + if (aggregate->community_hash && + aggregate->community_hash->count) { hash_iterate(aggregate->community_hash, bgp_aggr_community_prepare, &aggregate->community); + commerge = aggregate->community; + aggregate->community = community_uniq_sort(commerge); + if (commerge) + community_free(&commerge); } - - /* Increment refernce counter. - */ - aggr_community->refcnt++; } + + void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate, struct community *community) { struct community *aggr_community = NULL; struct community *ret_comm = NULL; - if ((aggregate == NULL) || (community == NULL)) - return; - - if (aggregate->community_hash == NULL) + if ((!aggregate) + || (!aggregate->community_hash) + || (!community)) return; /* Look-up the community in the hash. @@ -990,13 +1011,33 @@ void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate, aggr_community); community_free(&ret_comm); - community_free(&aggregate->community); + bgp_compute_aggregate_community_val(aggregate); + } + } +} + +void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct community *community) +{ + + struct community *aggr_community = NULL; + struct community *ret_comm = NULL; - /* Compute aggregate's community. - */ - hash_iterate(aggregate->community_hash, - bgp_aggr_community_prepare, - &aggregate->community); + if ((!aggregate) + || (!aggregate->community_hash) + || (!community)) + return; + + /* Look-up the community in the hash. + */ + aggr_community = bgp_aggr_community_lookup(aggregate, community); + if (aggr_community) { + aggr_community->refcnt--; + + if (aggr_community->refcnt == 0) { + ret_comm = hash_release(aggregate->community_hash, + aggr_community); + community_free(&ret_comm); } } } diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index f761a8f5e0..74a3a6b507 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -92,8 +92,16 @@ extern struct hash *community_hash(void); extern uint32_t community_val_get(struct community *com, int i); extern void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate, struct community *community); + +extern void bgp_compute_aggregate_community_val( + struct bgp_aggregate *aggregate); +extern void bgp_compute_aggregate_community_hash( + struct bgp_aggregate *aggregate, + struct community *community); extern void bgp_remove_community_from_aggregate(struct bgp_aggregate *aggregate, struct community *community); +extern void bgp_remove_comm_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct community *community); extern void bgp_aggr_community_remove(void *arg); #endif /* _QUAGGA_BGP_COMMUNITY_H */ diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 850b85aa6a..11f5a326df 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -1042,15 +1042,13 @@ static void *bgp_aggr_ecommunty_hash_alloc(void *p) static void bgp_aggr_ecommunity_prepare(struct hash_backet *hb, void *arg) { - struct ecommunity *ecommerge = NULL; struct ecommunity *hb_ecommunity = hb->data; struct ecommunity **aggr_ecommunity = arg; - if (*aggr_ecommunity) { - ecommerge = ecommunity_merge(*aggr_ecommunity, hb_ecommunity); - *aggr_ecommunity = ecommunity_uniq_sort(ecommerge); - ecommunity_free(&ecommerge); - } else + if (*aggr_ecommunity) + *aggr_ecommunity = ecommunity_merge(*aggr_ecommunity, + hb_ecommunity); + else *aggr_ecommunity = ecommunity_dup(hb_ecommunity); } @@ -1064,6 +1062,14 @@ void bgp_aggr_ecommunity_remove(void *arg) void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate, struct ecommunity *ecommunity) { + bgp_compute_aggregate_ecommunity_hash(aggregate, ecommunity); + bgp_compute_aggregate_ecommunity_val(aggregate); +} + + +void bgp_compute_aggregate_ecommunity_hash(struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity) +{ struct ecommunity *aggr_ecommunity = NULL; if ((aggregate == NULL) || (ecommunity == NULL)) @@ -1083,20 +1089,34 @@ void bgp_compute_aggregate_ecommunity(struct bgp_aggregate *aggregate, aggr_ecommunity = hash_get(aggregate->ecommunity_hash, ecommunity, bgp_aggr_ecommunty_hash_alloc); + } - /* Re-compute aggregate's ecommunity. - */ - if (aggregate->ecommunity) - ecommunity_free(&aggregate->ecommunity); + /* Increment reference counter. + */ + aggr_ecommunity->refcnt++; +} +void bgp_compute_aggregate_ecommunity_val(struct bgp_aggregate *aggregate) +{ + struct ecommunity *ecommerge = NULL; + + if (aggregate == NULL) + return; + + /* Re-compute aggregate's ecommunity. + */ + if (aggregate->ecommunity) + ecommunity_free(&aggregate->ecommunity); + if (aggregate->ecommunity_hash + && aggregate->ecommunity_hash->count) { hash_iterate(aggregate->ecommunity_hash, bgp_aggr_ecommunity_prepare, &aggregate->ecommunity); + ecommerge = aggregate->ecommunity; + aggregate->ecommunity = ecommunity_uniq_sort(ecommerge); + if (ecommerge) + ecommunity_free(&ecommerge); } - - /* Increment refernce counter. - */ - aggr_ecommunity->refcnt++; } void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, @@ -1105,10 +1125,9 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, struct ecommunity *aggr_ecommunity = NULL; struct ecommunity *ret_ecomm = NULL; - if ((aggregate == NULL) || (ecommunity == NULL)) - return; - - if (aggregate->ecommunity_hash == NULL) + if ((!aggregate) + || (!aggregate->ecommunity_hash) + || (!ecommunity)) return; /* Look-up the ecommunity in the hash. @@ -1121,14 +1140,33 @@ void bgp_remove_ecommunity_from_aggregate(struct bgp_aggregate *aggregate, ret_ecomm = hash_release(aggregate->ecommunity_hash, aggr_ecommunity); ecommunity_free(&ret_ecomm); + bgp_compute_aggregate_ecommunity_val(aggregate); + } + } +} + +void bgp_remove_ecomm_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity) +{ + + struct ecommunity *aggr_ecommunity = NULL; + struct ecommunity *ret_ecomm = NULL; - ecommunity_free(&aggregate->ecommunity); + if ((!aggregate) + || (!aggregate->ecommunity_hash) + || (!ecommunity)) + return; - /* Compute aggregate's ecommunity. - */ - hash_iterate(aggregate->ecommunity_hash, - bgp_aggr_ecommunity_prepare, - &aggregate->ecommunity); + /* Look-up the ecommunity in the hash. + */ + aggr_ecommunity = bgp_aggr_ecommunity_lookup(aggregate, ecommunity); + if (aggr_ecommunity) { + aggr_ecommunity->refcnt--; + + if (aggr_ecommunity->refcnt == 0) { + ret_ecomm = hash_release(aggregate->ecommunity_hash, + aggr_ecommunity); + ecommunity_free(&ret_ecomm); } } } diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 79be4ee422..249e5bf7de 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -190,9 +190,18 @@ extern int ecommunity_fill_pbr_action(struct ecommunity_val *ecom_eval, extern void bgp_compute_aggregate_ecommunity( struct bgp_aggregate *aggregate, struct ecommunity *ecommunity); + +extern void bgp_compute_aggregate_ecommunity_hash( + struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity); +extern void bgp_compute_aggregate_ecommunity_val( + struct bgp_aggregate *aggregate); extern void bgp_remove_ecommunity_from_aggregate( struct bgp_aggregate *aggregate, struct ecommunity *ecommunity); +extern void bgp_remove_ecomm_from_aggregate_hash( + struct bgp_aggregate *aggregate, + struct ecommunity *ecommunity); extern void bgp_aggr_ecommunity_remove(void *arg); #endif /* _QUAGGA_BGP_ECOMMUNITY_H */ diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index aeb290719a..3243ce96b5 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -555,15 +555,13 @@ static void *bgp_aggr_lcommunty_hash_alloc(void *p) static void bgp_aggr_lcommunity_prepare(struct hash_backet *hb, void *arg) { - struct lcommunity *lcommerge = NULL; struct lcommunity *hb_lcommunity = hb->data; struct lcommunity **aggr_lcommunity = arg; - if (*aggr_lcommunity) { - lcommerge = lcommunity_merge(*aggr_lcommunity, hb_lcommunity); - *aggr_lcommunity = lcommunity_uniq_sort(lcommerge); - lcommunity_free(&lcommerge); - } else + if (*aggr_lcommunity) + *aggr_lcommunity = lcommunity_merge(*aggr_lcommunity, + hb_lcommunity); + else *aggr_lcommunity = lcommunity_dup(hb_lcommunity); } @@ -577,6 +575,15 @@ void bgp_aggr_lcommunity_remove(void *arg) void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate, struct lcommunity *lcommunity) { + + bgp_compute_aggregate_lcommunity_hash(aggregate, lcommunity); + bgp_compute_aggregate_lcommunity_val(aggregate); +} + +void bgp_compute_aggregate_lcommunity_hash(struct bgp_aggregate *aggregate, + struct lcommunity *lcommunity) +{ + struct lcommunity *aggr_lcommunity = NULL; if ((aggregate == NULL) || (lcommunity == NULL)) @@ -596,20 +603,34 @@ void bgp_compute_aggregate_lcommunity(struct bgp_aggregate *aggregate, aggr_lcommunity = hash_get(aggregate->lcommunity_hash, lcommunity, bgp_aggr_lcommunty_hash_alloc); + } - /* Re-compute aggregate's lcommunity. - */ - if (aggregate->lcommunity) - lcommunity_free(&aggregate->lcommunity); + /* Increment reference counter. + */ + aggr_lcommunity->refcnt++; +} + +void bgp_compute_aggregate_lcommunity_val(struct bgp_aggregate *aggregate) +{ + struct lcommunity *lcommerge = NULL; + + if (aggregate == NULL) + return; + /* Re-compute aggregate's lcommunity. + */ + if (aggregate->lcommunity) + lcommunity_free(&aggregate->lcommunity); + if (aggregate->lcommunity_hash && + aggregate->lcommunity_hash->count) { hash_iterate(aggregate->lcommunity_hash, bgp_aggr_lcommunity_prepare, &aggregate->lcommunity); + lcommerge = aggregate->lcommunity; + aggregate->lcommunity = lcommunity_uniq_sort(lcommerge); + if (lcommerge) + lcommunity_free(&lcommerge); } - - /* Increment refernce counter. - */ - aggr_lcommunity->refcnt++; } void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate, @@ -618,10 +639,9 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate, struct lcommunity *aggr_lcommunity = NULL; struct lcommunity *ret_lcomm = NULL; - if ((aggregate == NULL) || (lcommunity == NULL)) - return; - - if (aggregate->lcommunity_hash == NULL) + if ((!aggregate) + || (!aggregate->lcommunity_hash) + || (!lcommunity)) return; /* Look-up the lcommunity in the hash. @@ -635,13 +655,33 @@ void bgp_remove_lcommunity_from_aggregate(struct bgp_aggregate *aggregate, aggr_lcommunity); lcommunity_free(&ret_lcomm); - lcommunity_free(&aggregate->lcommunity); + bgp_compute_aggregate_lcommunity_val(aggregate); + + } + } +} + +void bgp_remove_lcomm_from_aggregate_hash(struct bgp_aggregate *aggregate, + struct lcommunity *lcommunity) +{ + struct lcommunity *aggr_lcommunity = NULL; + struct lcommunity *ret_lcomm = NULL; - /* Compute aggregate's lcommunity. - */ - hash_iterate(aggregate->lcommunity_hash, - bgp_aggr_lcommunity_prepare, - &aggregate->lcommunity); + if ((!aggregate) + || (!aggregate->lcommunity_hash) + || (!lcommunity)) + return; + + /* Look-up the lcommunity in the hash. + */ + aggr_lcommunity = bgp_aggr_lcommunity_lookup(aggregate, lcommunity); + if (aggr_lcommunity) { + aggr_lcommunity->refcnt--; + + if (aggr_lcommunity->refcnt == 0) { + ret_lcomm = hash_release(aggregate->lcommunity_hash, + aggr_lcommunity); + lcommunity_free(&ret_lcomm); } } } diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index a512395492..7d63f4d26a 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -75,9 +75,19 @@ extern void lcommunity_del_val(struct lcommunity *lcom, uint8_t *ptr); extern void bgp_compute_aggregate_lcommunity( struct bgp_aggregate *aggregate, struct lcommunity *lcommunity); + +extern void bgp_compute_aggregate_lcommunity_hash( + struct bgp_aggregate *aggregate, + struct lcommunity *lcommunity); +extern void bgp_compute_aggregate_lcommunity_val( + struct bgp_aggregate *aggregate); + extern void bgp_remove_lcommunity_from_aggregate( struct bgp_aggregate *aggregate, struct lcommunity *lcommunity); +extern void bgp_remove_lcomm_from_aggregate_hash( + struct bgp_aggregate *aggregate, + struct lcommunity *lcommunity); extern void bgp_aggr_lcommunity_remove(void *arg); #endif /* _QUAGGA_BGP_LCOMMUNITY_H */ diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 05974bb2ba..37360a559a 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5927,33 +5927,41 @@ void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, */ /* Compute aggregate route's as-path. */ - bgp_compute_aggregate_aspath(aggregate, - pi->attr->aspath); + bgp_compute_aggregate_aspath_hash(aggregate, + pi->attr->aspath); /* Compute aggregate route's community. */ if (pi->attr->community) - bgp_compute_aggregate_community( + bgp_compute_aggregate_community_hash( aggregate, pi->attr->community); /* Compute aggregate route's extended community. */ if (pi->attr->ecommunity) - bgp_compute_aggregate_ecommunity( + bgp_compute_aggregate_ecommunity_hash( aggregate, pi->attr->ecommunity); /* Compute aggregate route's large community. */ if (pi->attr->lcommunity) - bgp_compute_aggregate_lcommunity( + bgp_compute_aggregate_lcommunity_hash( aggregate, pi->attr->lcommunity); } if (match) bgp_process(bgp, rn, afi, safi); } + if (aggregate->as_set) { + bgp_compute_aggregate_aspath_val(aggregate); + bgp_compute_aggregate_community_val(aggregate); + bgp_compute_aggregate_ecommunity_val(aggregate); + bgp_compute_aggregate_lcommunity_val(aggregate); + } + + bgp_unlock_node(top); @@ -6034,28 +6042,28 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, if (aggregate->as_set) { /* Remove as-path from aggregate. */ - bgp_remove_aspath_from_aggregate( + bgp_remove_aspath_from_aggregate_hash( aggregate, pi->attr->aspath); if (pi->attr->community) /* Remove community from aggregate. */ - bgp_remove_community_from_aggregate( + bgp_remove_comm_from_aggregate_hash( aggregate, pi->attr->community); if (pi->attr->ecommunity) /* Remove ecommunity from aggregate. */ - bgp_remove_ecommunity_from_aggregate( + bgp_remove_ecomm_from_aggregate_hash( aggregate, pi->attr->ecommunity); if (pi->attr->lcommunity) /* Remove lcommunity from aggregate. */ - bgp_remove_lcommunity_from_aggregate( + bgp_remove_lcomm_from_aggregate_hash( aggregate, pi->attr->lcommunity); } @@ -6066,6 +6074,17 @@ void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, if (match) bgp_process(bgp, rn, afi, safi); } + if (aggregate->as_set) { + aspath_free(aggregate->aspath); + aggregate->aspath = NULL; + if (aggregate->community) + community_free(&aggregate->community); + if (aggregate->ecommunity) + ecommunity_free(&aggregate->ecommunity); + if (aggregate->lcommunity) + lcommunity_free(&aggregate->lcommunity); + } + bgp_unlock_node(top); } diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index de7b05bdd9..4b6af935e0 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -570,8 +570,7 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg) vty_out(vty, " Created: %s", timestamp_string(updgrp->uptime)); filter = &updgrp->conf->filter[updgrp->afi][updgrp->safi]; if (filter->map[RMAP_OUT].name) - vty_out(vty, " Outgoing route map: %s%s\n", - filter->map[RMAP_OUT].map ? "X" : "", + vty_out(vty, " Outgoing route map: %s\n", filter->map[RMAP_OUT].name); vty_out(vty, " MRAI value (seconds): %d\n", updgrp->conf->v_routeadv); if (updgrp->conf->change_local_as) @@ -613,6 +612,9 @@ static int update_group_show_walkcb(struct update_group *updgrp, void *arg) subgrp->peer_refreshes_combined); vty_out(vty, " Merge checks triggered: %u\n", subgrp->merge_checks_triggered); + vty_out(vty, " Coalesce Time: %u%s\n", + (UPDGRP_INST(subgrp->update_group))->coalesce_time, + subgrp->t_coalesce ? "(Running)" : ""); vty_out(vty, " Version: %" PRIu64 "\n", subgrp->version); vty_out(vty, " Packet queue length: %d\n", bpacket_queue_length(SUBGRP_PKTQ(subgrp))); diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 21f1dff60d..5c1483a768 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -324,8 +324,9 @@ static int subgroup_coalesce_timer(struct thread *thread) subgrp = THREAD_ARG(thread); if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0)) zlog_debug("u%" PRIu64 ":s%" PRIu64 - " announcing routes upon coalesce timer expiry", - (SUBGRP_UPDGRP(subgrp))->id, subgrp->id); + " announcing routes upon coalesce timer expiry(%u ms)", + (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, + subgrp->v_coalesce), subgrp->t_coalesce = NULL; subgrp->v_coalesce = 0; subgroup_announce_route(subgrp); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 9d45d96987..320f1ec96c 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -1202,7 +1202,7 @@ struct peer { uint8_t last_reset_cause[BGP_MAX_PACKET_SIZE]; /* The kind of route-map Flags.*/ - uint8_t rmap_type; + uint16_t rmap_type; #define PEER_RMAP_TYPE_IN (1 << 0) /* neighbor route-map in */ #define PEER_RMAP_TYPE_OUT (1 << 1) /* neighbor route-map out */ #define PEER_RMAP_TYPE_NETWORK (1 << 2) /* network route-map */ diff --git a/configure.ac b/configure.ac index 6c1b35b5f2..88f1c4f627 100755 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ ## AC_PREREQ([2.60]) -AC_INIT([frr], [7.2-dev], [https://github.com/frrouting/frr/issues]) +AC_INIT([frr], [7.3-dev], [https://github.com/frrouting/frr/issues]) PACKAGE_URL="https://frrouting.org/" AC_SUBST([PACKAGE_URL]) PACKAGE_FULLNAME="FRRouting" @@ -1452,6 +1452,12 @@ if test "x$enable_pcreposix" = "xyes"; then fi AC_SUBST([HAVE_LIBPCREPOSIX]) +dnl ########################################################################## +dnl test "${enable_clippy_only}" != "yes" +fi +dnl END OF LARGE if block +dnl ########################################################################## + dnl ------------------ dnl check C-Ares library dnl ------------------ @@ -1462,12 +1468,6 @@ PKG_CHECK_MODULES([CARES], [libcares], [ ]) AM_CONDITIONAL([CARES], [$c_ares_found]) -dnl ########################################################################## -dnl test "${enable_clippy_only}" != "yes" -fi -dnl END OF LARGE if block -dnl ########################################################################## - dnl ---------------------------------------------------------------------------- dnl figure out if domainname is available in the utsname struct (GNU extension). @@ -1535,9 +1535,11 @@ case "$host_os" in no) ;; yes) + if test "${enable_clippy_only}" != "yes"; then if test "$c_ares_found" != "true" ; then AC_MSG_ERROR([nhrpd requires libcares. Please install c-ares and its -dev headers.]) fi + fi NHRPD="nhrpd" ;; *) @@ -2041,9 +2043,11 @@ if test "${enable_capabilities}" != "no"; then case "$host_os" in linux*) + if test "${enable_clippy_only}" != "yes"; then if test "$frr_ac_lcaps" != "yes"; then AC_MSG_ERROR([libcap and/or its headers were not found. Running FRR without libcap support built in causes a huge performance penalty.]) fi + fi ;; esac else diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst index 32ca5707d2..525a31d486 100644 --- a/doc/user/bfd.rst +++ b/doc/user/bfd.rst @@ -79,8 +79,8 @@ BFDd Commands `vrf` selects which domain we want to use. -.. index:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}] -.. clicmd:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrfname}] +.. index:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}] +.. clicmd:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}] Stops and removes the selected peer. @@ -89,8 +89,8 @@ BFDd Commands Show all configured BFD peers information and current status. -.. index:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json] -.. clicmd:: show bfd [vrf NAME$vrfname] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json] +.. index:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json] +.. clicmd:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json] Show status for a specific BFD peer. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index 7b3cdf2c4b..8edd19026d 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -2396,6 +2396,23 @@ Displaying Routes by AS Path Print a summary of neighbor connections for the specified AFI/SAFI combination. +Displaying Update Group Information +----------------------------------- + +..index:: show bgp update-groups SUBGROUP-ID [advertise-queue|advertised-routes|packet-queue] +..clicmd:: show bgp update-groups [advertise-queue|advertised-routes|packet-queue] + + Display Information about each individual update-group being used. + If SUBGROUP-ID is specified only display about that particular group. If + advertise-queue is specified the list of routes that need to be sent + to the peers in the update-group is displayed, advertised-routes means + the list of routes we have sent to the peers in the update-group and + packet-queue specifies the list of packets in the queue to be sent. + +..index:: show bgp update-groups statistics +..clicmd:: show bgp update-groups statistics + + Display Information about update-group events in FRR. .. _bgp-route-reflector: diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index b7283d83de..5d2cfbc337 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -663,19 +663,30 @@ kernel. .. clicmd:: ip protocol PROTOCOL route-map ROUTEMAP Apply a route-map filter to routes for the specified protocol. PROTOCOL can - be **any** or one of + be: - - system, - - kernel, + - any, + - babel, + - bgp, - connected, - - static, - - rip, - - ripng, + - eigrp, + - isis, + - kernel, + - nhrp, + - openfabric, - ospf, - ospf6, - - isis, - - bgp, - - hsls. + - rip, + - sharp, + - static, + - ripng, + - table, + - vnc. + + If you choose any as the option that will cause all protocols that are sending + routes to zebra. You can specify a :dfn:`ip protocol PROTOCOL route-map ROUTEMAP` + on a per vrf basis, by entering this command under vrf mode for the vrf you + want to apply the route-map against. .. index:: set src ADDRESS .. clicmd:: set src ADDRESS diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile index 815983a394..88c8f88f81 100644 --- a/docker/alpine/Dockerfile +++ b/docker/alpine/Dockerfile @@ -9,7 +9,8 @@ RUN source /src/alpine/APKBUILD.in \ --no-cache \ --update-cache \ $makedepends \ - gzip + gzip \ + && pip install pytest COPY . /src ARG PKGVER @@ -29,6 +30,8 @@ RUN echo 'http://dl-cdn.alpinelinux.org/alpine/edge/testing' >> /etc/apk/reposit abuild \ alpine-conf \ alpine-sdk \ + py-pip \ + && pip install pytest \ && setup-apkcache /var/cache/apk \ && mkdir -p /pkgs/apk \ && echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c index c7ffbf9f0e..3e09ec41bb 100644 --- a/eigrpd/eigrp_network.c +++ b/eigrpd/eigrp_network.c @@ -55,12 +55,15 @@ static void eigrp_network_run_interface(struct eigrp *, struct prefix *, int eigrp_sock_init(struct vrf *vrf) { - int eigrp_sock; + int eigrp_sock = -1; int ret; #ifdef IP_HDRINCL int hincl = 1; #endif + if (!vrf) + return eigrp_sock; + frr_with_privs(&eigrpd_privs) { eigrp_sock = vrf_socket( AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP, vrf->vrf_id, diff --git a/include/linux/fib_rules.h b/include/linux/fib_rules.h index bc6688012c..232df14e12 100644 --- a/include/linux/fib_rules.h +++ b/include/linux/fib_rules.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_FIB_RULES_H #define __LINUX_FIB_RULES_H @@ -22,13 +23,23 @@ struct fib_rule_hdr { __u8 tos; __u8 table; - __u8 res1; /* reserved */ + __u8 res1; /* reserved */ __u8 res2; /* reserved */ __u8 action; __u32 flags; }; +struct fib_rule_uid_range { + __u32 start; + __u32 end; +}; + +struct fib_rule_port_range { + __u16 start; + __u16 end; +}; + enum { FRA_UNSPEC, FRA_DST, /* destination address */ @@ -43,7 +54,7 @@ enum { FRA_UNUSED5, FRA_FWMARK, /* mark */ FRA_FLOW, /* flow/class id */ - FRA_UNUSED6, + FRA_TUN_ID, FRA_SUPPRESS_IFGROUP, FRA_SUPPRESS_PREFIXLEN, FRA_TABLE, /* Extended table id */ @@ -51,6 +62,11 @@ enum { FRA_OIFNAME, FRA_PAD, FRA_L3MDEV, /* iif or oif is l3mdev goto its table */ + FRA_UID_RANGE, /* UID range */ + FRA_PROTOCOL, /* Originator of the rule */ + FRA_IP_PROTO, /* ip proto */ + FRA_SPORT_RANGE, /* sport */ + FRA_DPORT_RANGE, /* dport */ __FRA_MAX }; diff --git a/include/linux/if_addr.h b/include/linux/if_addr.h index a924606f36..dfcf3ce009 100644 --- a/include/linux/if_addr.h +++ b/include/linux/if_addr.h @@ -34,6 +34,7 @@ enum { IFA_MULTICAST, IFA_FLAGS, IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ + IFA_TARGET_NETNSID, __IFA_MAX, }; @@ -63,7 +64,9 @@ struct ifa_cacheinfo { }; /* backwards compatibility for userspace */ +#ifndef __KERNEL__ #define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) #define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) +#endif #endif diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h index 156f4434ca..fb79481cb2 100644 --- a/include/linux/if_bridge.h +++ b/include/linux/if_bridge.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * Linux ethernet bridge * @@ -10,8 +11,8 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef _LINUX_IF_BRIDGE_H -#define _LINUX_IF_BRIDGE_H +#ifndef _UAPI_LINUX_IF_BRIDGE_H +#define _UAPI_LINUX_IF_BRIDGE_H #include <linux/types.h> #include <linux/if_ether.h> @@ -96,7 +97,7 @@ struct __fdb_entry { __u32 ageing_timer_value; __u8 port_hi; __u8 pad0; - __u16 unused; + __u16 vlan; }; /* Bridge Flags */ @@ -236,6 +237,7 @@ struct br_mdb_entry { #define MDB_PERMANENT 1 __u8 state; #define MDB_FLAGS_OFFLOAD (1 << 0) +#define MDB_FLAGS_FAST_LEAVE (1 << 1) __u8 flags; __u16 vid; struct { @@ -291,4 +293,4 @@ struct br_mcast_stats { __u64 mcast_bytes[BR_MCAST_DIR_SIZE]; __u64 mcast_packets[BR_MCAST_DIR_SIZE]; }; -#endif /* _LINUX_IF_BRIDGE_H */ +#endif /* _UAPI_LINUX_IF_BRIDGE_H */ diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 1f97d0560b..22a45914a2 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -1,5 +1,6 @@ -#ifndef _LINUX_IF_LINK_H -#define _LINUX_IF_LINK_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_IF_LINK_H +#define _UAPI_LINUX_IF_LINK_H #include <linux/types.h> #include <linux/netlink.h> @@ -158,6 +159,14 @@ enum { IFLA_PAD, IFLA_XDP, IFLA_EVENT, + IFLA_NEW_NETNSID, + IFLA_IF_NETNSID, + IFLA_TARGET_NETNSID = IFLA_IF_NETNSID, /* new alias */ + IFLA_CARRIER_UP_COUNT, + IFLA_CARRIER_DOWN_COUNT, + IFLA_NEW_IFINDEX, + IFLA_MIN_MTU, + IFLA_MAX_MTU, __IFLA_MAX }; @@ -165,8 +174,10 @@ enum { #define IFLA_MAX (__IFLA_MAX - 1) /* backwards compatibility for userspace */ +#ifndef __KERNEL__ #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg)))) #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg)) +#endif enum { IFLA_INET_UNSPEC, @@ -276,6 +287,7 @@ enum { IFLA_BR_MCAST_STATS_ENABLED, IFLA_BR_MCAST_IGMP_VERSION, IFLA_BR_MCAST_MLD_VERSION, + IFLA_BR_VLAN_STATS_PER_PORT, __IFLA_BR_MAX, }; @@ -323,6 +335,14 @@ enum { IFLA_BRPORT_MCAST_TO_UCAST, IFLA_BRPORT_VLAN_TUNNEL, IFLA_BRPORT_BCAST_FLOOD, + IFLA_BRPORT_GROUP_FWD_MASK, + IFLA_BRPORT_NEIGH_SUPPRESS, + IFLA_BRPORT_ISOLATED, + IFLA_BRPORT_BACKUP_PORT, + IFLA_BRPORT_PEER_LINK = 60, /* MLAG peer link */ + IFLA_BRPORT_DUAL_LINK, /* MLAG Dual Connected link */ + IFLA_BRPORT_GROUP_FWD_MASKHI, + IFLA_BRPORT_DUAL_LINK_READY, __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) @@ -448,6 +468,16 @@ enum { #define IFLA_MACSEC_MAX (__IFLA_MACSEC_MAX - 1) +/* XFRM section */ +enum { + IFLA_XFRM_UNSPEC, + IFLA_XFRM_LINK, + IFLA_XFRM_IF_ID, + __IFLA_XFRM_MAX +}; + +#define IFLA_XFRM_MAX (__IFLA_XFRM_MAX - 1) + enum macsec_validation_type { MACSEC_VALIDATE_DISABLED = 0, MACSEC_VALIDATE_CHECK = 1, @@ -460,6 +490,7 @@ enum macsec_validation_type { enum { IFLA_IPVLAN_UNSPEC, IFLA_IPVLAN_MODE, + IFLA_IPVLAN_FLAGS, __IFLA_IPVLAN_MAX }; @@ -472,6 +503,9 @@ enum ipvlan_mode { IPVLAN_MODE_MAX }; +#define IPVLAN_F_PRIVATE 0x01 +#define IPVLAN_F_VEPA 0x02 + /* VXLAN section */ enum { IFLA_VXLAN_UNSPEC, @@ -502,6 +536,7 @@ enum { IFLA_VXLAN_COLLECT_METADATA, IFLA_VXLAN_LABEL, IFLA_VXLAN_GPE, + IFLA_VXLAN_TTL_INHERIT, __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) @@ -585,6 +620,8 @@ enum { IFLA_BOND_AD_USER_PORT_KEY, IFLA_BOND_AD_ACTOR_SYSTEM, IFLA_BOND_TLB_DYNAMIC_LB, + IFLA_BOND_CL_START = 60, + IFLA_BOND_AD_LACP_BYPASS = IFLA_BOND_CL_START, __IFLA_BOND_MAX, }; @@ -612,6 +649,9 @@ enum { IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, + + IFLA_BOND_SLAVE_CL_START = 50, + IFLA_BOND_SLAVE_AD_RX_BYPASS = IFLA_BOND_SLAVE_CL_START, __IFLA_BOND_SLAVE_MAX, }; @@ -721,6 +761,8 @@ enum { IFLA_VF_STATS_BROADCAST, IFLA_VF_STATS_MULTICAST, IFLA_VF_STATS_PAD, + IFLA_VF_STATS_RX_DROPPED, + IFLA_VF_STATS_TX_DROPPED, __IFLA_VF_STATS_MAX, }; @@ -872,6 +914,7 @@ enum { enum { LINK_XSTATS_TYPE_UNSPEC, LINK_XSTATS_TYPE_BRIDGE, + LINK_XSTATS_TYPE_BOND, __LINK_XSTATS_TYPE_MAX }; #define LINK_XSTATS_TYPE_MAX (__LINK_XSTATS_TYPE_MAX - 1) @@ -902,6 +945,7 @@ enum { XDP_ATTACHED_DRV, XDP_ATTACHED_SKB, XDP_ATTACHED_HW, + XDP_ATTACHED_MULTI, }; enum { @@ -910,6 +954,9 @@ enum { IFLA_XDP_ATTACHED, IFLA_XDP_FLAGS, IFLA_XDP_PROG_ID, + IFLA_XDP_DRV_PROG_ID, + IFLA_XDP_SKB_PROG_ID, + IFLA_XDP_HW_PROG_ID, __IFLA_XDP_MAX, }; @@ -925,4 +972,43 @@ enum { IFLA_EVENT_BONDING_OPTIONS, /* change in bonding options */ }; -#endif /* _LINUX_IF_LINK_H */ +/* tun section */ + +enum { + IFLA_TUN_UNSPEC, + IFLA_TUN_OWNER, + IFLA_TUN_GROUP, + IFLA_TUN_TYPE, + IFLA_TUN_PI, + IFLA_TUN_VNET_HDR, + IFLA_TUN_PERSIST, + IFLA_TUN_MULTI_QUEUE, + IFLA_TUN_NUM_QUEUES, + IFLA_TUN_NUM_DISABLED_QUEUES, + __IFLA_TUN_MAX, +}; + +#define IFLA_TUN_MAX (__IFLA_TUN_MAX - 1) + +/* rmnet section */ + +#define RMNET_FLAGS_INGRESS_DEAGGREGATION (1U << 0) +#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1) +#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2) +#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3) + +enum { + IFLA_RMNET_UNSPEC, + IFLA_RMNET_MUX_ID, + IFLA_RMNET_FLAGS, + __IFLA_RMNET_MAX, +}; + +#define IFLA_RMNET_MAX (__IFLA_RMNET_MAX - 1) + +struct ifla_rmnet_flags { + __u32 flags; + __u32 mask; +}; + +#endif /* _UAPI_LINUX_IF_LINK_H */ diff --git a/include/linux/lwtunnel.h b/include/linux/lwtunnel.h index 3298426271..de696ca12f 100644 --- a/include/linux/lwtunnel.h +++ b/include/linux/lwtunnel.h @@ -1,5 +1,6 @@ -#ifndef _LWTUNNEL_H_ -#define _LWTUNNEL_H_ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LWTUNNEL_H_ +#define _UAPI_LWTUNNEL_H_ #include <linux/types.h> @@ -67,4 +68,4 @@ enum { #define LWT_BPF_MAX_HEADROOM 256 -#endif /* _LWTUNNEL_H_ */ +#endif /* _UAPI_LWTUNNEL_H_ */ diff --git a/include/linux/mpls_iptunnel.h b/include/linux/mpls_iptunnel.h index 1a0e57b45a..521f2e605f 100644 --- a/include/linux/mpls_iptunnel.h +++ b/include/linux/mpls_iptunnel.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * mpls tunnel api * @@ -10,8 +11,8 @@ * 2 of the License, or (at your option) any later version. */ -#ifndef _LINUX_MPLS_IPTUNNEL_H -#define _LINUX_MPLS_IPTUNNEL_H +#ifndef _UAPI_LINUX_MPLS_IPTUNNEL_H +#define _UAPI_LINUX_MPLS_IPTUNNEL_H /* MPLS tunnel attributes * [RTA_ENCAP] = { @@ -27,4 +28,4 @@ enum { }; #define MPLS_IPTUNNEL_MAX (__MPLS_IPTUNNEL_MAX - 1) -#endif /* _LINUX_MPLS_IPTUNNEL_H */ +#endif /* _UAPI_LINUX_MPLS_IPTUNNEL_H */ diff --git a/include/linux/neighbour.h b/include/linux/neighbour.h index 3199d28980..cd144e3099 100644 --- a/include/linux/neighbour.h +++ b/include/linux/neighbour.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef __LINUX_NEIGHBOUR_H #define __LINUX_NEIGHBOUR_H @@ -27,6 +28,7 @@ enum { NDA_MASTER, NDA_LINK_NETNSID, NDA_SRC_VNI, + NDA_PROTOCOL, /* Originator of entry */ __NDA_MAX }; @@ -42,6 +44,7 @@ enum { #define NTF_PROXY 0x08 /* == ATF_PUBL */ #define NTF_EXT_LEARNED 0x10 #define NTF_OFFLOADED 0x20 +#define NTF_STICKY 0x40 #define NTF_ROUTER 0x80 /* diff --git a/include/linux/net_namespace.h b/include/linux/net_namespace.h index 9a92b7e14a..0187c74d88 100644 --- a/include/linux/net_namespace.h +++ b/include/linux/net_namespace.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ /* Copyright (c) 2015 6WIND S.A. * Author: Nicolas Dichtel <nicolas.dichtel@6wind.com> * @@ -5,8 +6,8 @@ * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. */ -#ifndef _LINUX_NET_NAMESPACE_H_ -#define _LINUX_NET_NAMESPACE_H_ +#ifndef _UAPI_LINUX_NET_NAMESPACE_H_ +#define _UAPI_LINUX_NET_NAMESPACE_H_ /* Attributes of RTM_NEWNSID/RTM_GETNSID messages */ enum { @@ -20,4 +21,4 @@ enum { #define NETNSA_MAX (__NETNSA_MAX - 1) -#endif /* _LINUX_NET_NAMESPACE_H_ */ +#endif /* _UAPI_LINUX_NET_NAMESPACE_H_ */ diff --git a/include/linux/netlink.h b/include/linux/netlink.h index 0b2c29bd08..0a4d733177 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef __LINUX_NETLINK_H -#define __LINUX_NETLINK_H +#ifndef _UAPI__LINUX_NETLINK_H +#define _UAPI__LINUX_NETLINK_H #include <linux/kernel.h> #include <linux/socket.h> /* for __kernel_sa_family_t */ @@ -147,12 +147,15 @@ enum nlmsgerr_attrs { #define NETLINK_PKTINFO 3 #define NETLINK_BROADCAST_ERROR 4 #define NETLINK_NO_ENOBUFS 5 +#ifndef __KERNEL__ #define NETLINK_RX_RING 6 #define NETLINK_TX_RING 7 +#endif #define NETLINK_LISTEN_ALL_NSID 8 #define NETLINK_LIST_MEMBERSHIPS 9 #define NETLINK_CAP_ACK 10 #define NETLINK_EXT_ACK 11 +#define NETLINK_GET_STRICT_CHK 12 struct nl_pktinfo { __u32 group; @@ -175,6 +178,7 @@ struct nl_mmap_hdr { __u32 nm_gid; }; +#ifndef __KERNEL__ enum nl_mmap_status { NL_MMAP_STATUS_UNUSED, NL_MMAP_STATUS_RESERVED, @@ -186,6 +190,7 @@ enum nl_mmap_status { #define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO #define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT) #define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr)) +#endif #define NET_MAJOR 36 /* Major 36 is reserved for networking */ @@ -244,4 +249,4 @@ struct nla_bitfield32 { __u32 selector; }; -#endif /* __LINUX_NETLINK_H */ +#endif /* _UAPI__LINUX_NETLINK_H */ diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h index 813e9e0767..ce2a623abb 100644 --- a/include/linux/rtnetlink.h +++ b/include/linux/rtnetlink.h @@ -1,5 +1,6 @@ -#ifndef __LINUX_RTNETLINK_H -#define __LINUX_RTNETLINK_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI__LINUX_RTNETLINK_H +#define _UAPI__LINUX_RTNETLINK_H #include <linux/types.h> #include <linux/netlink.h> @@ -149,6 +150,20 @@ enum { RTM_NEWCACHEREPORT = 96, #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT + RTM_NEWCHAIN = 100, +#define RTM_NEWCHAIN RTM_NEWCHAIN + RTM_DELCHAIN, +#define RTM_DELCHAIN RTM_DELCHAIN + RTM_GETCHAIN, +#define RTM_GETCHAIN RTM_GETCHAIN + + RTM_NEWNEXTHOP = 104, +#define RTM_NEWNEXTHOP RTM_NEWNEXTHOP + RTM_DELNEXTHOP, +#define RTM_DELNEXTHOP RTM_DELNEXTHOP + RTM_GETNEXTHOP, +#define RTM_GETNEXTHOP RTM_GETNEXTHOP + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -253,6 +268,11 @@ enum { #define RTPROT_DHCP 16 /* DHCP client */ #define RTPROT_MROUTED 17 /* Multicast daemon */ #define RTPROT_BABEL 42 /* Babel daemon */ +#define RTPROT_BGP 186 /* BGP Routes */ +#define RTPROT_ISIS 187 /* ISIS Routes */ +#define RTPROT_OSPF 188 /* OSPF Routes */ +#define RTPROT_RIP 189 /* RIP Routes */ +#define RTPROT_EIGRP 192 /* EIGRP Routes */ /* rtm_scope @@ -326,6 +346,10 @@ enum rtattr_type_t { RTA_PAD, RTA_UID, RTA_TTL_PROPAGATE, + RTA_IP_PROTO, + RTA_SPORT, + RTA_DPORT, + RTA_NH_ID, __RTA_MAX }; @@ -430,6 +454,8 @@ enum { #define RTAX_QUICKACK RTAX_QUICKACK RTAX_CC_ALGO, #define RTAX_CC_ALGO RTAX_CC_ALGO + RTAX_FASTOPEN_NO_COOKIE, +#define RTAX_FASTOPEN_NO_COOKIE RTAX_FASTOPEN_NO_COOKIE __RTAX_MAX }; @@ -538,9 +564,19 @@ struct tcmsg { int tcm_ifindex; __u32 tcm_handle; __u32 tcm_parent; +/* tcm_block_index is used instead of tcm_parent + * in case tcm_ifindex == TCM_IFINDEX_MAGIC_BLOCK + */ +#define tcm_block_index tcm_parent __u32 tcm_info; }; +/* For manipulation of filters in shared block, tcm_ifindex is set to + * TCM_IFINDEX_MAGIC_BLOCK, and tcm_parent is aliased to tcm_block_index + * which is the block index. + */ +#define TCM_IFINDEX_MAGIC_BLOCK (0xFFFFFFFFU) + enum { TCA_UNSPEC, TCA_KIND, @@ -554,6 +590,9 @@ enum { TCA_PAD, TCA_DUMP_INVISIBLE, TCA_CHAIN, + TCA_HW_OFFLOAD, + TCA_INGRESS_BLOCK, + TCA_EGRESS_BLOCK, __TCA_MAX }; @@ -586,6 +625,7 @@ enum { #define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1) +#ifndef __KERNEL__ /* RTnetlink multicast groups - backwards compatibility for userspace */ #define RTMGRP_LINK 1 #define RTMGRP_NOTIFY 2 @@ -606,6 +646,7 @@ enum { #define RTMGRP_DECnet_ROUTE 0x4000 #define RTMGRP_IPV6_PREFIX 0x20000 +#endif /* RTnetlink multicast groups */ enum rtnetlink_groups { @@ -671,6 +712,8 @@ enum rtnetlink_groups { #define RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV4_MROUTE_R RTNLGRP_IPV6_MROUTE_R, #define RTNLGRP_IPV6_MROUTE_R RTNLGRP_IPV6_MROUTE_R + RTNLGRP_NEXTHOP, +#define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -715,4 +758,4 @@ enum { -#endif /* __LINUX_RTNETLINK_H */ +#endif /* _UAPI__LINUX_RTNETLINK_H */ diff --git a/include/linux/socket.h b/include/linux/socket.h index 8c1e501774..8eb9602170 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -1,5 +1,6 @@ -#ifndef _LINUX_SOCKET_H -#define _LINUX_SOCKET_H +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_SOCKET_H +#define _UAPI_LINUX_SOCKET_H /* * Desired design of maximum size and alignment (see RFC2553) @@ -18,4 +19,4 @@ struct __kernel_sockaddr_storage { /* _SS_MAXSIZE value minus size of ss_family */ } __attribute__ ((aligned(_K_SS_ALIGNSIZE))); /* force desired alignment */ -#endif /* _LINUX_SOCKET_H */ +#endif /* _UAPI_LINUX_SOCKET_H */ diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c index 9b368cc404..d2ec6ff566 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -254,6 +254,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, reason ? reason : "unspecified"); } + circuit->adj_state_changes++; #ifndef FABRICD /* send northbound notification */ isis_notif_adj_state_change(adj, new_state, reason); diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index e3541644aa..b77c8ce352 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -144,6 +144,13 @@ struct isis_circuit { uint32_t desig_changes[2]; /* lanLxDesignatedIntermediateSystemChanges */ uint32_t rej_adjacencies; /* rejectedAdjacencies */ + /* + * Counters as in ietf-isis@2019-09-09.yang + */ + uint32_t id_len_mismatches; /* id-len-mismatch */ + uint32_t max_area_addr_mismatches; /* max-area-addresses-mismatch */ + uint32_t auth_type_failures; /*authentication-type-fails */ + uint32_t auth_failures; /* authentication-fails */ QOBJ_FIELDS }; diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 7f49e9d89a..718924daf2 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -243,7 +243,7 @@ int main(int argc, char **argv, char **envp) mt_init(); /* create the global 'isis' instance */ - isis_new(1); + isis_new(1, VRF_DEFAULT); isis_zebra_init(master); isis_bfd_init(); diff --git a/isisd/isis_northbound.c b/isisd/isis_northbound.c index bd61918697..1e21efa7ce 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -49,6 +49,23 @@ #include "lib/vrf.h" /* + * Helper functions. + */ +static const char *isis_yang_adj_state(enum isis_adj_state state) +{ + switch (state) { + case ISIS_ADJ_DOWN: + return "down"; + case ISIS_ADJ_UP: + return "up"; + case ISIS_ADJ_INITIALIZING: + return "init"; + default: + return "failed"; + } +} + +/* * XPath: /frr-isisd:isis/instance */ static int isis_instance_create(enum nb_event event, @@ -1542,9 +1559,9 @@ static int lib_interface_isis_create(enum nb_event event, /* check if interface mtu is sufficient. If the area has not * been created yet, assume default MTU for the area */ - ifp = nb_running_get_entry(dnode, NULL, true); + ifp = nb_running_get_entry(dnode, NULL, false); /* zebra might not know yet about the MTU - nothing we can do */ - if (ifp->mtu == 0) + if (!ifp || ifp->mtu == 0) break; actual_mtu = if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu; @@ -2304,6 +2321,368 @@ static int lib_interface_isis_multi_topology_ipv6_dstsrc_modify( } /* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency + */ +static const void * +lib_interface_isis_adjacencies_adjacency_get_next(const void *parent_list_entry, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj, *adj_next = NULL; + struct list *list; + struct listnode *node, *node_next; + + /* Get first adjacency. */ + if (list_entry == NULL) { + ifp = (struct interface *)parent_list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; + level++) { + adj = listnode_head( + circuit->u.bc.adjdb[level - 1]); + if (adj) + break; + } + break; + case CIRCUIT_T_P2P: + adj = circuit->u.p2p.neighbor; + break; + default: + adj = NULL; + break; + } + + return adj; + } + + /* Get next adjacency. */ + adj = (struct isis_adjacency *)list_entry; + circuit = adj->circuit; + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + list = circuit->u.bc.adjdb[adj->level - 1]; + node = listnode_lookup(list, adj); + node_next = listnextnode(node); + if (node_next) + adj_next = listgetdata(node_next); + else if (adj->level == ISIS_LEVEL1) { + /* + * Once we finish the L1 adjacencies, move to the L2 + * adjacencies list. + */ + list = circuit->u.bc.adjdb[ISIS_LEVEL2 - 1]; + adj_next = listnode_head(list); + } + break; + case CIRCUIT_T_P2P: + /* P2P circuits have at most one adjacency. */ + default: + break; + } + + return adj_next; +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_enum(xpath, adj->level); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, sysid_print(adj->sysid)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint32(xpath, adj->circuit->circuit_id); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, snpa_print(adj->snpa)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint16(xpath, adj->hold_time); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem( + const char *xpath, const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_uint8(xpath, adj->prio[adj->level - 1]); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state + */ +static struct yang_data * +lib_interface_isis_adjacencies_adjacency_state_get_elem(const char *xpath, + const void *list_entry) +{ + const struct isis_adjacency *adj = list_entry; + + return yang_data_new_string(xpath, isis_yang_adj_state(adj->adj_state)); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_changes_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->adj_state_changes); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_number_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + struct isis_adjacency *adj; + struct listnode *node; + uint32_t total = 0; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + /* + * TODO: keep track of the number of adjacencies instead of calculating + * it on demand. + */ + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS; level++) { + for (ALL_LIST_ELEMENTS_RO( + circuit->u.bc.adjdb[level - 1], node, adj)) + total++; + } + break; + case CIRCUIT_T_P2P: + adj = circuit->u.p2p.neighbor; + if (adj) + total = 1; + break; + default: + break; + } + + return yang_data_new_uint32(xpath, total); +} + +/* + * XPath: /frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_init_fails_get_elem(const char *xpath, + const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->init_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects + */ +static struct yang_data * +lib_interface_isis_event_counters_adjacency_rejects_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->rej_adjacencies); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch + */ +static struct yang_data * +lib_interface_isis_event_counters_id_len_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->id_len_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch + */ +static struct yang_data * +lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->max_area_addr_mismatches); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_authentication_type_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_type_failures); +} + +/* + * XPath: + * /frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails + */ +static struct yang_data * +lib_interface_isis_event_counters_authentication_fails_get_elem( + const char *xpath, const void *list_entry) +{ + struct interface *ifp; + struct isis_circuit *circuit; + + ifp = (struct interface *)list_entry; + if (!ifp) + return NULL; + + circuit = circuit_scan_by_ifp(ifp); + if (!circuit) + return NULL; + + return yang_data_new_uint32(xpath, circuit->auth_failures); +} + +/* * NOTIFICATIONS */ static void notif_prep_instance_hdr(const char *xpath, @@ -2545,19 +2924,7 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj, listnode_add(arguments, data); snprintf(xpath_arg, sizeof(xpath_arg), "%s/state", xpath); - switch (new_state) { - case ISIS_ADJ_DOWN: - data = yang_data_new_string(xpath_arg, "down"); - break; - case ISIS_ADJ_UP: - data = yang_data_new_string(xpath_arg, "up"); - break; - case ISIS_ADJ_INITIALIZING: - data = yang_data_new_string(xpath_arg, "init"); - break; - default: - data = yang_data_new_string(xpath_arg, "failed"); - } + data = yang_data_new_string(xpath_arg, isis_yang_adj_state(new_state)); listnode_add(arguments, data); if (new_state == ISIS_ADJ_DOWN) { snprintf(xpath_arg, sizeof(xpath_arg), "%s/reason", xpath); @@ -3484,6 +3851,102 @@ const struct frr_yang_module_info frr_isisd_info = { }, }, { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency", + .cbs = { + .get_next = lib_interface_isis_adjacencies_adjacency_get_next, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sys-type", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sys_type_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-sysid", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_sysid_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-extended-circuit-id", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_extended_circuit_id_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-snpa", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_snpa_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/hold-timer", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_hold_timer_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/neighbor-priority", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_neighbor_priority_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/adjacencies/adjacency/state", + .cbs = { + .get_elem = lib_interface_isis_adjacencies_adjacency_state_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-changes", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_changes_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-number", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_number_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/init-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_init_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/adjacency-rejects", + .cbs = { + .get_elem = lib_interface_isis_event_counters_adjacency_rejects_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/id-len-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_id_len_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/max-area-addresses-mismatch", + .cbs = { + .get_elem = lib_interface_isis_event_counters_max_area_addresses_mismatch_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-type-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_type_fails_get_elem, + } + }, + { + .xpath = "/frr-interface:lib/interface/frr-isisd:isis/event-counters/authentication-fails", + .cbs = { + .get_elem = lib_interface_isis_event_counters_authentication_fails_get_elem, + } + }, + { .xpath = NULL, }, } diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index ecfce392ff..46b013ddd0 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -576,6 +576,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (p2p_hello) { if (circuit->circ_type != CIRCUIT_T_P2P) { zlog_warn("p2p hello on non p2p circuit"); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "p2p hello on non p2p circuit", @@ -586,6 +587,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, } else { if (circuit->circ_type != CIRCUIT_T_BROADCAST) { zlog_warn("lan hello on non broadcast circuit"); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "lan hello on non broadcast circuit", @@ -598,6 +600,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, zlog_debug( "level %d LAN Hello received over circuit with externalDomain = true", level); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, @@ -614,6 +617,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, circuit->area->area_tag, circuit->interface->name); } + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Interface level mismatch", raw_pdu); @@ -643,6 +647,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, "ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %" PRIu16, circuit->area->area_tag, pdu_name, circuit->interface->name, iih.pdu_len); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency(circuit, "Invalid PDU length", raw_pdu); @@ -654,6 +659,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, flog_err(EC_ISIS_PACKET, "Level %d LAN Hello with Circuit Type %d", level, iih.circ_type); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "LAN Hello with wrong IS-level", raw_pdu); @@ -667,6 +673,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream), circuit->rcv_stream, &iih.tlvs, &error_log)) { zlog_warn("isis_unpack_tlvs() failed: %s", error_log); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency(circuit, "Failed to unpack TLVs", raw_pdu); @@ -685,6 +692,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, if (!iih.tlvs->protocols_supported.count) { zlog_warn("No supported protocols TLV in %s", pdu_name); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "No supported protocols TLV", raw_pdu); @@ -702,11 +710,14 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, /* send northbound notification */ stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, pdu_end - pdu_start); - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -715,6 +726,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, zlog_warn( "ISIS-Adj (%s): Received IIH with own sysid - discard", circuit->area->area_tag); + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Received IIH with our own sysid", raw_pdu); @@ -752,6 +764,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit, "ISIS-Adj (%s): Neither IPv4 nor IPv6 considered usable. Ignoring IIH", circuit->area->area_tag); } + circuit->rej_adjacencies++; #ifndef FABRICD isis_notif_reject_adjacency( circuit, "Neither IPv4 not IPv6 considered usable", @@ -940,11 +953,14 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit, hdr.lsp_id); #ifndef FABRICD /* send northbound notification */ - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -1373,12 +1389,15 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit, /* send northbound notification */ stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start, pdu_end - pdu_start); - if (auth_code == ISIS_AUTH_FAILURE) + if (auth_code == ISIS_AUTH_FAILURE) { + circuit->auth_failures++; isis_notif_authentication_failure(circuit, raw_pdu); - else /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + } else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */ + circuit->auth_type_failures++; isis_notif_authentication_type_failure(circuit, raw_pdu); + } #endif /* ifndef FABRICD */ goto out; } @@ -1614,6 +1633,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) "IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8 ", while the parameter for this IS is %u", id_len, ISIS_SYS_ID_LEN); + circuit->id_len_mismatches++; #ifndef FABRICD /* send northbound notification */ isis_notif_id_len_mismatch(circuit, id_len, raw_pdu); @@ -1666,6 +1686,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa) "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8 " while the parameter for this IS is %u", max_area_addrs, isis->max_area_addrs); + circuit->max_area_addr_mismatches++; #ifndef FABRICD /* send northbound notification */ isis_notif_max_area_addr_mismatch(circuit, max_area_addrs, diff --git a/isisd/isis_te.c b/isisd/isis_te.c index 44fa45d02b..9871d2bcb9 100644 --- a/isisd/isis_te.c +++ b/isisd/isis_te.c @@ -81,8 +81,7 @@ void isis_link_params_update(struct isis_circuit *circuit, return; /* Sanity Check */ - if ((circuit == NULL) || (ifp == NULL) - || (circuit->state != C_STATE_UP)) + if ((ifp == NULL) || (circuit->state != C_STATE_UP)) return; zlog_debug("TE(%s): Update circuit parameters for interface %s", diff --git a/isisd/isisd.c b/isisd/isisd.c index 67f557ab50..029a9e0688 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -75,12 +75,13 @@ int clear_isis_neighbor_common(struct vty *, const char *id); int isis_config_write(struct vty *); -void isis_new(unsigned long process_id) +void isis_new(unsigned long process_id, vrf_id_t vrf_id) { isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis)); /* * Default values */ + isis->vrf_id = vrf_id; isis->max_area_addrs = 3; isis->process_id = process_id; isis->router_id = 0; diff --git a/isisd/isisd.h b/isisd/isisd.h index 308f018c19..f825b6ecb4 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -62,6 +62,7 @@ extern struct zebra_privs_t isisd_privs; struct fabricd; struct isis { + vrf_id_t vrf_id; unsigned long process_id; int sysid_set; uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */ @@ -189,7 +190,7 @@ struct isis_area { DECLARE_QOBJ_TYPE(isis_area) void isis_init(void); -void isis_new(unsigned long); +void isis_new(unsigned long process_id, vrf_id_t vrf_id); struct isis_area *isis_area_create(const char *); struct isis_area *isis_area_lookup(const char *); int isis_area_get(struct vty *vty, const char *area_tag); @@ -1196,7 +1196,7 @@ void if_link_params_free(struct interface *ifp) */ DEFPY_NOSH (interface, interface_cmd, - "interface IFNAME [vrf NAME$vrfname]", + "interface IFNAME [vrf NAME$vrf_name]", "Select an interface to configure\n" "Interface's name\n" VRF_CMD_HELP_STR) @@ -1206,8 +1206,8 @@ DEFPY_NOSH (interface, struct interface *ifp; int ret; - if (!vrfname) - vrfname = VRF_DEFAULT_NAME; + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; /* * This command requires special handling to maintain backward @@ -1216,7 +1216,7 @@ DEFPY_NOSH (interface, * interface is found, then a new one should be created on the default * VRF. */ - VRF_GET_ID(vrf_id, vrfname, false); + VRF_GET_ID(vrf_id, vrf_name, false); ifp = if_lookup_by_name_all_vrf(ifname); if (ifp && ifp->vrf_id != vrf_id) { struct vrf *vrf; @@ -1227,24 +1227,24 @@ DEFPY_NOSH (interface, */ if (vrf_id != VRF_DEFAULT) { vty_out(vty, "%% interface %s not in %s vrf\n", ifname, - vrfname); + vrf_name); return CMD_WARNING_CONFIG_FAILED; } /* * Special case 2: a VRF name was *not* specified, and the found * interface is associated to a VRF other than the default one. - * Update vrf_id and vrfname to account for that. + * Update vrf_id and vrf_name to account for that. */ vrf = vrf_lookup_by_id(ifp->vrf_id); assert(vrf); vrf_id = ifp->vrf_id; - vrfname = vrf->name; + vrf_name = vrf->name; } snprintf(xpath_list, sizeof(xpath_list), "/frr-interface:lib/interface[name='%s'][vrf='%s']", ifname, - vrfname); + vrf_name); nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL); ret = nb_cli_apply_changes(vty, xpath_list); @@ -1267,20 +1267,20 @@ DEFPY_NOSH (interface, DEFPY (no_interface, no_interface_cmd, - "no interface IFNAME [vrf NAME$vrfname]", + "no interface IFNAME [vrf NAME$vrf_name]", NO_STR "Delete a pseudo interface's configuration\n" "Interface's name\n" VRF_CMD_HELP_STR) { - if (!vrfname) - vrfname = VRF_DEFAULT_NAME; + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL); return nb_cli_apply_changes( vty, "/frr-interface:lib/interface[name='%s'][vrf='%s']", - ifname, vrfname); + ifname, vrf_name); } static void cli_show_interface(struct vty *vty, struct lyd_node *dnode, diff --git a/lib/nexthop_group.c b/lib/nexthop_group.c index abe2096cec..9564321d38 100644 --- a/lib/nexthop_group.c +++ b/lib/nexthop_group.c @@ -475,7 +475,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\ |INTERFACE$intf\ >\ - [nexthop-vrf NAME$name]", + [nexthop-vrf NAME$vrf_name]", NO_STR "Specify one of the nexthops in this ECMP group\n" "v4 Address\n" @@ -490,7 +490,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, struct nexthop *nh; bool legal; - legal = nexthop_group_parse_nexthop(&nhop, addr, intf, name); + legal = nexthop_group_parse_nexthop(&nhop, addr, intf, vrf_name); if (nhop.type == NEXTHOP_TYPE_IPV6 && IN6_IS_ADDR_LINKLOCAL(&nhop.gate.ipv6)) { @@ -502,7 +502,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, nh = nexthop_exists(&nhgc->nhg, &nhop); if (no) { - nexthop_group_unsave_nhop(nhgc, name, addr, intf); + nexthop_group_unsave_nhop(nhgc, vrf_name, addr, intf); if (nh) { _nexthop_del(&nhgc->nhg, nh); @@ -520,7 +520,7 @@ DEFPY(ecmp_nexthops, ecmp_nexthops_cmd, _nexthop_add(&nhgc->nhg.nexthop, nh); } - nexthop_group_save_nhop(nhgc, name, addr, intf); + nexthop_group_save_nhop(nhgc, vrf_name, addr, intf); if (legal && nhg_hooks.add_nexthop) nhg_hooks.add_nexthop(nhgc, nh); @@ -472,6 +472,14 @@ static const struct cmd_variable_handler vrf_var_handlers[] = { .varname = "vrf", .completions = vrf_autocomplete, }, + { + .varname = "vrf_name", + .completions = vrf_autocomplete, + }, + { + .varname = "nexthop_vrf", + .completions = vrf_autocomplete, + }, {.completions = NULL}, }; diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 692c84ad08..4d7c75a330 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -355,8 +355,6 @@ void ospf6_interface_state_update(struct interface *ifp) oi = (struct ospf6_interface *)ifp->info; if (oi == NULL) return; - if (oi->area == NULL) - return; if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) return; @@ -683,6 +681,9 @@ int interface_up(struct thread *thread) oi = (struct ospf6_interface *)THREAD_ARG(thread); assert(oi && oi->interface); + if (!oi->type_cfg) + oi->type = ospf6_default_iftype(oi->interface); + /* * Remove old pointer. If this thread wasn't a timer this * operation won't make a difference, because it is already NULL. @@ -774,8 +775,7 @@ int interface_up(struct thread *thread) } /* decide next interface state */ - if ((if_is_pointopoint(oi->interface)) - || (oi->type == OSPF_IFTYPE_POINTOPOINT)) { + if (oi->type == OSPF_IFTYPE_POINTOPOINT) { ospf6_interface_state_change(OSPF6_INTERFACE_POINTTOPOINT, oi); } else if (oi->priority == 0) ospf6_interface_state_change(OSPF6_INTERFACE_DROTHER, oi); @@ -880,6 +880,19 @@ int interface_down(struct thread *thread) } +static const char *ospf6_iftype_str(uint8_t iftype) +{ + switch (iftype) { + case OSPF_IFTYPE_LOOPBACK: + return "LOOPBACK"; + case OSPF_IFTYPE_BROADCAST: + return "BROADCAST"; + case OSPF_IFTYPE_POINTOPOINT: + return "POINTOPOINT"; + } + return "UNKNOWN"; +} + /* show specified interface structure */ static int ospf6_interface_show(struct vty *vty, struct interface *ifp) { @@ -888,23 +901,16 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp) struct prefix *p; struct listnode *i; char strbuf[PREFIX2STR_BUFFER], drouter[32], bdrouter[32]; - const char *type; + uint8_t default_iftype; struct timeval res, now; char duration[32]; struct ospf6_lsa *lsa; - /* check physical interface type */ - if (if_is_loopback(ifp)) - type = "LOOPBACK"; - else if (if_is_broadcast(ifp)) - type = "BROADCAST"; - else if (if_is_pointopoint(ifp)) - type = "POINTOPOINT"; - else - type = "UNKNOWN"; + default_iftype = ospf6_default_iftype(ifp); vty_out(vty, "%s is %s, type %s\n", ifp->name, - (if_is_operative(ifp) ? "up" : "down"), type); + (if_is_operative(ifp) ? "up" : "down"), + ospf6_iftype_str(default_iftype)); vty_out(vty, " Interface ID: %d\n", ifp->ifindex); if (ifp->info == NULL) { @@ -913,6 +919,10 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp) } else oi = (struct ospf6_interface *)ifp->info; + if (if_is_operative(ifp) && oi->type != default_iftype) + vty_out(vty, " Operating as type %s\n", + ospf6_iftype_str(oi->type)); + vty_out(vty, " Internet Address:\n"); for (ALL_LIST_ELEMENTS_RO(ifp->connected, i, c)) { @@ -1809,6 +1819,8 @@ DEFUN (ipv6_ospf6_network, } assert(oi); + oi->type_cfg = true; + if (strncmp(argv[idx_network]->arg, "b", 1) == 0) { if (oi->type == OSPF_IFTYPE_BROADCAST) return CMD_SUCCESS; @@ -1849,6 +1861,8 @@ DEFUN (no_ipv6_ospf6_network, return CMD_SUCCESS; } + oi->type_cfg = false; + type = ospf6_default_iftype(ifp); if (oi->type == type) { return CMD_SUCCESS; @@ -1916,13 +1930,10 @@ static int config_write_ospf6_interface(struct vty *vty) if (oi->mtu_ignore) vty_out(vty, " ipv6 ospf6 mtu-ignore\n"); - if (oi->type != ospf6_default_iftype(ifp)) { - if (oi->type == OSPF_IFTYPE_POINTOPOINT) - vty_out(vty, - " ipv6 ospf6 network point-to-point\n"); - else if (oi->type == OSPF_IFTYPE_BROADCAST) - vty_out(vty, " ipv6 ospf6 network broadcast\n"); - } + if (oi->type_cfg && oi->type == OSPF_IFTYPE_POINTOPOINT) + vty_out(vty, " ipv6 ospf6 network point-to-point\n"); + else if (oi->type_cfg && oi->type == OSPF_IFTYPE_BROADCAST) + vty_out(vty, " ipv6 ospf6 network broadcast\n"); ospf6_bfd_write_config(vty, oi); diff --git a/ospf6d/ospf6_interface.h b/ospf6d/ospf6_interface.h index e0c39a29b4..53a8910f4d 100644 --- a/ospf6d/ospf6_interface.h +++ b/ospf6d/ospf6_interface.h @@ -55,6 +55,7 @@ struct ospf6_interface { /* Network Type */ uint8_t type; + bool type_cfg; /* Router Priority */ uint8_t priority; diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c index b551dbdfa6..0a9f1c6f7c 100644 --- a/ospf6d/ospf6_lsdb.c +++ b/ospf6d/ospf6_lsdb.c @@ -298,13 +298,17 @@ struct ospf6_lsa *ospf6_lsdb_next(const struct route_node *iterend, void ospf6_lsdb_remove_all(struct ospf6_lsdb *lsdb) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; if (lsdb == NULL) return; - for (ALL_LSDB(lsdb, lsa)) + for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); ospf6_lsdb_remove(lsa, lsdb); + } } void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa) @@ -319,9 +323,12 @@ void ospf6_lsdb_lsa_unlock(struct ospf6_lsa *lsa) int ospf6_lsdb_maxage_remover(struct ospf6_lsdb *lsdb) { int reschedule = 0; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; - for (ALL_LSDB(lsdb, lsa)) { + for (iterend = ospf6_lsdb_head(lsdb, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); if (!OSPF6_LSA_IS_MAXAGE(lsa)) continue; if (lsa->retrans_count != 0) { diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c index 4acb5e3b2e..da42a24252 100644 --- a/ospf6d/ospf6_message.c +++ b/ospf6d/ospf6_message.c @@ -1866,7 +1866,8 @@ int ospf6_dbdesc_send(struct thread *thread) int ospf6_dbdesc_send_newone(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; unsigned int size = 0; on = (struct ospf6_neighbor *)THREAD_ARG(thread); @@ -1876,7 +1877,10 @@ int ospf6_dbdesc_send_newone(struct thread *thread) structure) so that ospf6_send_dbdesc () can send those LSAs */ size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc); - for (ALL_LSDB(on->summary_list, lsa)) { + + for (iterend = ospf6_lsdb_head(on->summary_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); if (size + sizeof(struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) { ospf6_lsdb_lsa_unlock(lsa); @@ -2019,7 +2023,8 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) struct ospf6_lsupdate *lsupdate; uint8_t *p; int lsa_cnt; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; on = (struct ospf6_neighbor *)THREAD_ARG(thread); on->thread_send_lsupdate = (struct thread *)NULL; @@ -2044,7 +2049,9 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) /* lsupdate_list lists those LSA which doesn't need to be retransmitted. remove those from the list */ - for (ALL_LSDB(on->lsupdate_list, lsa)) { + for (iterend = ospf6_lsdb_head(on->lsupdate_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); /* MTU check */ if ((p - sendbuf + (unsigned int)OSPF6_LSA_SIZE(lsa->header)) > ospf6_packet_max(on->ospf6_if)) { @@ -2074,7 +2081,7 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread) p += OSPF6_LSA_SIZE(lsa->header); lsa_cnt++; - assert(lsa->lock == 2); + assert(lsa->lock == 1); ospf6_lsdb_remove(lsa, on->lsupdate_list); } @@ -2202,7 +2209,8 @@ int ospf6_lsupdate_send_interface(struct thread *thread) struct ospf6_lsupdate *lsupdate; uint8_t *p; int lsa_cnt; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; oi = (struct ospf6_interface *)THREAD_ARG(thread); oi->thread_send_lsupdate = (struct thread *)NULL; @@ -2228,7 +2236,9 @@ int ospf6_lsupdate_send_interface(struct thread *thread) p = (uint8_t *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate)); lsa_cnt = 0; - for (ALL_LSDB(oi->lsupdate_list, lsa)) { + for (iterend = ospf6_lsdb_head(oi->lsupdate_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); /* MTU check */ if ((p - sendbuf + ((unsigned int)OSPF6_LSA_SIZE(lsa->header))) > ospf6_packet_max(oi)) { @@ -2263,7 +2273,7 @@ int ospf6_lsupdate_send_interface(struct thread *thread) p += OSPF6_LSA_SIZE(lsa->header); lsa_cnt++; - assert(lsa->lock == 2); + assert(lsa->lock == 1); ospf6_lsdb_remove(lsa, oi->lsupdate_list); } @@ -2289,7 +2299,8 @@ int ospf6_lsack_send_neighbor(struct thread *thread) struct ospf6_neighbor *on; struct ospf6_header *oh; uint8_t *p; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; int lsa_cnt = 0; on = (struct ospf6_neighbor *)THREAD_ARG(thread); @@ -2312,7 +2323,9 @@ int ospf6_lsack_send_neighbor(struct thread *thread) p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header)); - for (ALL_LSDB(on->lsack_list, lsa)) { + for (iterend = ospf6_lsdb_head(on->lsack_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); /* MTU check */ if (p - sendbuf + sizeof(struct ospf6_lsa_header) > ospf6_packet_max(on->ospf6_if)) { @@ -2340,7 +2353,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread) memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header)); p += sizeof(struct ospf6_lsa_header); - assert(lsa->lock == 2); + assert(lsa->lock == 1); ospf6_lsdb_remove(lsa, on->lsack_list); lsa_cnt++; } @@ -2367,7 +2380,8 @@ int ospf6_lsack_send_interface(struct thread *thread) struct ospf6_interface *oi; struct ospf6_header *oh; uint8_t *p; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; int lsa_cnt = 0; oi = (struct ospf6_interface *)THREAD_ARG(thread); @@ -2391,7 +2405,9 @@ int ospf6_lsack_send_interface(struct thread *thread) p = (uint8_t *)((caddr_t)oh + sizeof(struct ospf6_header)); - for (ALL_LSDB(oi->lsack_list, lsa)) { + for (iterend = ospf6_lsdb_head(oi->lsack_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); /* MTU check */ if (p - sendbuf + sizeof(struct ospf6_lsa_header) > ospf6_packet_max(oi)) { @@ -2409,7 +2425,7 @@ int ospf6_lsack_send_interface(struct thread *thread) memcpy(p, lsa->header, sizeof(struct ospf6_lsa_header)); p += sizeof(struct ospf6_lsa_header); - assert(lsa->lock == 2); + assert(lsa->lock == 1); ospf6_lsdb_remove(lsa, oi->lsack_list); lsa_cnt++; } diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 46dc621ae7..4318db5225 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -112,11 +112,15 @@ struct ospf6_neighbor *ospf6_neighbor_create(uint32_t router_id, void ospf6_neighbor_delete(struct ospf6_neighbor *on) { - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) { + + for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } @@ -287,7 +291,8 @@ int twoway_received(struct thread *thread) int negotiation_done(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -301,7 +306,10 @@ int negotiation_done(struct thread *thread) /* clear ls-list */ ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) { + + for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } @@ -495,7 +503,8 @@ int seqnumber_mismatch(struct thread *thread) int bad_lsreq(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -514,7 +523,10 @@ int bad_lsreq(struct thread *thread) ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) { + + for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } @@ -532,7 +544,8 @@ int bad_lsreq(struct thread *thread) int oneway_received(struct thread *thread) { struct ospf6_neighbor *on; - struct ospf6_lsa *lsa; + struct ospf6_lsa *lsa, *lsa_next; + const struct route_node *iterend; on = (struct ospf6_neighbor *)THREAD_ARG(thread); assert(on); @@ -549,7 +562,9 @@ int oneway_received(struct thread *thread) ospf6_lsdb_remove_all(on->summary_list); ospf6_lsdb_remove_all(on->request_list); - for (ALL_LSDB(on->retrans_list, lsa)) { + for (iterend = ospf6_lsdb_head(on->retrans_list, 0, 0, 0, &lsa); lsa; + lsa = lsa_next) { + lsa_next = ospf6_lsdb_next(iterend, lsa); ospf6_decrement_retrans_count(lsa); ospf6_lsdb_remove(lsa, on->retrans_list); } @@ -618,7 +633,7 @@ static void ospf6_neighbor_show(struct vty *vty, struct ospf6_neighbor *on) snprintf(deadtime, sizeof(deadtime), "%02ld:%02ld:%02ld", h, m, s); /* Neighbor State */ - if (if_is_pointopoint(on->ospf6_if->interface)) + if (on->ospf6_if->type == OSPF_IFTYPE_POINTOPOINT) snprintf(nstate, sizeof(nstate), "PointToPoint"); else { if (on->router_id == on->drouter) diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c index fc7c6177d7..1ba89f3bd6 100644 --- a/ospf6d/ospf6_snmp.c +++ b/ospf6d/ospf6_snmp.c @@ -1130,9 +1130,9 @@ static uint8_t *ospfv3IfEntry(struct variable *v, oid *name, size_t *length, return SNMP_INTEGER(ntohl(oi->area->area_id)); break; case OSPFv3IFTYPE: - if (if_is_broadcast(oi->interface)) + if (oi->type == OSPF_IFTYPE_BROADCAST) return SNMP_INTEGER(1); - else if (if_is_pointopoint(oi->interface)) + else if (oi->type == OSPF_IFTYPE_POINTOPOINT) return SNMP_INTEGER(3); else break; /* Unknown, don't put anything */ diff --git a/ospf6d/ospf6_top.c b/ospf6d/ospf6_top.c index 40c6123810..95dafff84e 100644 --- a/ospf6d/ospf6_top.c +++ b/ospf6d/ospf6_top.c @@ -136,7 +136,7 @@ static void ospf6_top_brouter_hook_remove(struct ospf6_route *route) ospf6_abr_originate_summary(route); } -static struct ospf6 *ospf6_create(void) +static struct ospf6 *ospf6_create(vrf_id_t vrf_id) { struct ospf6 *o; @@ -144,6 +144,7 @@ static struct ospf6 *ospf6_create(void) /* initialize */ monotime(&o->starttime); + o->vrf_id = vrf_id; o->area_list = list_new(); o->area_list->cmp = ospf6_area_cmp; o->lsdb = ospf6_lsdb_create(o); @@ -325,7 +326,7 @@ DEFUN_NOSH (router_ospf6, OSPF6_STR) { if (ospf6 == NULL) { - ospf6 = ospf6_create(); + ospf6 = ospf6_create(VRF_DEFAULT); if (ospf6->router_id == 0) ospf6_router_id_update(); } diff --git a/ospf6d/ospf6_top.h b/ospf6d/ospf6_top.h index 381027dcff..ba41fca65b 100644 --- a/ospf6d/ospf6_top.h +++ b/ospf6d/ospf6_top.h @@ -31,6 +31,9 @@ struct ospf6_master { /* OSPFv3 top level data structure */ struct ospf6 { + /* The relevant vrf_id */ + vrf_id_t vrf_id; + /* my router id */ uint32_t router_id; diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 359f869c42..ae04402f49 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -711,7 +711,7 @@ pbr_nht_individual_nexthop_gw_update(struct pbr_nexthop_cache *pnhc, } if (pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX - || pnhc->nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { + || pnhc->nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) { /* GATEWAY_IFINDEX type shouldn't resolve to group */ if (pnhi->nhr->nexthop_num > 1) { diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c index 5e7addc9d2..a6e764bbb0 100644 --- a/pbrd/pbr_vty.c +++ b/pbrd/pbr_vty.c @@ -254,7 +254,7 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, <A.B.C.D|X:X::X:X>$addr [INTERFACE$intf]\ |INTERFACE$intf\ >\ - [nexthop-vrf NAME$name]", + [nexthop-vrf NAME$vrf_name]", NO_STR "Set for the PBR-MAP\n" "Specify one of the nexthops in this map\n" @@ -276,13 +276,13 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd, return CMD_WARNING_CONFIG_FAILED; } - if (name) - vrf = vrf_lookup_by_name(name); + if (vrf_name) + vrf = vrf_lookup_by_name(vrf_name); else vrf = vrf_lookup_by_id(VRF_DEFAULT); if (!vrf) { - vty_out(vty, "Specified: %s is non-existent\n", name); + vty_out(vty, "Specified: %s is non-existent\n", vrf_name); return CMD_WARNING_CONFIG_FAILED; } diff --git a/pimd/pim_pim.c b/pimd/pim_pim.c index 12b28ed9af..cd2d306f3d 100644 --- a/pimd/pim_pim.c +++ b/pimd/pim_pim.c @@ -574,6 +574,7 @@ int pim_msg_send(int fd, struct in_addr src, struct in_addr dst, ip->ip_id = htons(++ip_id); ip->ip_hl = 5; ip->ip_v = 4; + ip->ip_tos = IPTOS_PREC_INTERNETCONTROL; ip->ip_p = PIM_IP_PROTO_PIM; ip->ip_src = src; ip->ip_dst = dst; diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c index 82255cd3b0..7f03e18389 100644 --- a/pimd/pim_sock.c +++ b/pimd/pim_sock.c @@ -255,6 +255,12 @@ int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, } } + /* Set Tx socket DSCP byte */ + if (setsockopt_ipv4_tos(fd, IPTOS_PREC_INTERNETCONTROL)) { + zlog_warn("can't set sockopt IP_TOS to PIM/IGMP socket %d: %s", + fd, safe_strerror(errno)); + } + return fd; } diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index b0db23f54a..37cb12548c 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -1180,12 +1180,6 @@ void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; uint32_t mask = PIM_OIF_FLAG_PROTO_PIM; - int input_iface_vif_index = 0; - struct pim_instance *pim; - struct pim_interface *pim_ifp; - - pim_ifp = ch->interface->info; - pim = pim_ifp->pim; if (PIM_DEBUG_PIM_TRACE) { char source_str[INET_ADDRSTRLEN]; @@ -1203,55 +1197,6 @@ void pim_forward_start(struct pim_ifchannel *ch) inet_ntoa(up->upstream_addr)); } - /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, - as part of mroute_del called by pim_forward_stop. - */ - if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) { - struct prefix src, grp; - - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = up->sg.grp; - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = up->sg.src; - - if (pim_ecmp_nexthop_lookup(pim, &up->rpf.source_nexthop, &src, - &grp, 0)) - input_iface_vif_index = pim_if_find_vifindex_by_ifindex( - pim, up->rpf.source_nexthop.interface->ifindex); - - if (input_iface_vif_index < 1) { - if (PIM_DEBUG_PIM_TRACE) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", up->sg.src, - source_str, sizeof(source_str)); - zlog_debug( - "%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); - } - pim_channel_oil_change_iif(pim, up->channel_oil, - MAXVIFS, - __PRETTY_FUNCTION__); - } - - else - pim_channel_oil_change_iif(pim, up->channel_oil, - input_iface_vif_index, - __PRETTY_FUNCTION__); - - if (PIM_DEBUG_TRACE) { - struct interface *in_intf = pim_if_find_by_vif_index( - pim, input_iface_vif_index); - zlog_debug( - "%s: Update channel_oil IIF %s VIFI %d entry %s ", - __PRETTY_FUNCTION__, - in_intf ? in_intf->name : "Unknown", - input_iface_vif_index, up->sg_str); - } - } - if (up->flags & PIM_UPSTREAM_FLAG_MASK_SRC_IGMP) mask = PIM_OIF_FLAG_PROTO_IGMP; diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c index 60cfb2e486..486ccf6bfe 100644 --- a/sharpd/sharp_vty.c +++ b/sharpd/sharp_vty.c @@ -39,7 +39,7 @@ #endif DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, - "sharp watch [vrf NAME$name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]", + "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop> [connected$connected]", "Sharp routing Protocol\n" "Watch for changes\n" "The vrf we would like to watch if non-default\n" @@ -54,12 +54,12 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, struct prefix p; bool type_import; - if (!name) - name = VRF_DEFAULT_NAME; - vrf = vrf_lookup_by_name(name); + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { vty_out(vty, "The vrf NAME specified: %s does not exist\n", - name); + vrf_name); return CMD_WARNING; } @@ -83,7 +83,7 @@ DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd, } DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, - "sharp watch [vrf NAME$name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]", + "sharp watch [vrf NAME$vrf_name] <nexthop$n A.B.C.D$nhop|import$import A.B.C.D/M$inhop> [connected$connected]", "Sharp routing Protocol\n" "Watch for changes\n" "The vrf we would like to watch if non-default\n" @@ -98,12 +98,12 @@ DEFPY(watch_nexthop_v4, watch_nexthop_v4_cmd, struct prefix p; bool type_import; - if (!name) - name = VRF_DEFAULT_NAME; - vrf = vrf_lookup_by_name(name); + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; + vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { vty_out(vty, "The vrf NAME specified: %s does not exist\n", - name); + vrf_name); return CMD_WARNING; } @@ -162,7 +162,7 @@ DEFPY (install_routes_data_dump, DEFPY (install_routes, install_routes_cmd, - "sharp install routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", + "sharp install routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> <nexthop <A.B.C.D$nexthop4|X:X::X:X$nexthop6>|nexthop-group NHGNAME$nexthop_group> (1-1000000)$routes [instance (0-255)$instance] [repeat (2-1000)$rpt]", "Sharp routing Protocol\n" "install some routes\n" "Routes to install\n" @@ -209,13 +209,13 @@ DEFPY (install_routes, } sg.r.orig_prefix = prefix; - if (!name) - name = VRF_DEFAULT_NAME; + if (!vrf_name) + vrf_name = VRF_DEFAULT_NAME; - vrf = vrf_lookup_by_name(name); + vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { vty_out(vty, "The vrf NAME specified: %s does not exist\n", - name); + vrf_name); return CMD_WARNING; } @@ -252,7 +252,7 @@ DEFPY (install_routes, } DEFPY(vrf_label, vrf_label_cmd, - "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$name label (0-100000)$label", + "sharp label <ip$ipv4|ipv6$ipv6> vrf NAME$vrf_name label (0-100000)$label", "Sharp Routing Protocol\n" "Give a vrf a label\n" "Pop and forward for IPv4\n" @@ -264,10 +264,10 @@ DEFPY(vrf_label, vrf_label_cmd, struct vrf *vrf; afi_t afi = (ipv4) ? AFI_IP : AFI_IP6; - if (strcmp(name, "default") == 0) + if (strcmp(vrf_name, "default") == 0) vrf = vrf_lookup_by_id(VRF_DEFAULT); else - vrf = vrf_lookup_by_name(name); + vrf = vrf_lookup_by_name(vrf_name); if (!vrf) { vty_out(vty, "Unable to find vrf you silly head"); @@ -283,7 +283,7 @@ DEFPY(vrf_label, vrf_label_cmd, DEFPY (remove_routes, remove_routes_cmd, - "sharp remove routes [vrf NAME$name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]", + "sharp remove routes [vrf NAME$vrf_name] <A.B.C.D$start4|X:X::X:X$start6> (1-1000000)$routes [instance (0-255)$instance]", "Sharp Routing Protocol\n" "Remove some routes\n" "Routes to remove\n" @@ -314,10 +314,10 @@ DEFPY (remove_routes, prefix.u.prefix6 = start6; } - vrf = vrf_lookup_by_name(name ? name : VRF_DEFAULT_NAME); + vrf = vrf_lookup_by_name(vrf_name ? vrf_name : VRF_DEFAULT_NAME); if (!vrf) { vty_out(vty, "The vrf NAME specified: %s does not exist\n", - name ? name : VRF_DEFAULT_NAME); + vrf_name ? vrf_name : VRF_DEFAULT_NAME); return CMD_WARNING; } diff --git a/staticd/static_vrf.c b/staticd/static_vrf.c index 9dd25fbdd1..abb64aad3f 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -27,6 +27,7 @@ #include "static_memory.h" #include "static_vrf.h" #include "static_routes.h" +#include "static_zebra.h" #include "static_vty.h" static void zebra_stable_node_cleanup(struct route_table *table, @@ -76,6 +77,8 @@ static int static_vrf_new(struct vrf *vrf) static int static_vrf_enable(struct vrf *vrf) { + static_zebra_vrf_register(vrf); + static_fixup_vrf_ids(vrf->info); /* @@ -89,6 +92,7 @@ static int static_vrf_enable(struct vrf *vrf) static int static_vrf_disable(struct vrf *vrf) { + static_zebra_vrf_unregister(vrf); return 0; } diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index 1965c2968e..2944cdad32 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -526,3 +526,17 @@ void static_zebra_init(void) static_nht_hash_cmp, "Static Nexthop Tracking hash"); } + +void static_zebra_vrf_register(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + zclient_send_reg_requests(zclient, vrf->vrf_id); +} + +void static_zebra_vrf_unregister(struct vrf *vrf) +{ + if (vrf->vrf_id == VRF_DEFAULT) + return; + zclient_send_dereg_requests(zclient, vrf->vrf_id); +} diff --git a/staticd/static_zebra.h b/staticd/static_zebra.h index 15f5410b81..962dc3908f 100644 --- a/staticd/static_zebra.h +++ b/staticd/static_zebra.h @@ -28,4 +28,7 @@ extern void static_zebra_route_add(struct route_node *rn, struct static_route *si_changed, vrf_id_t vrf_id, safi_t safi, bool install); extern void static_zebra_init(void); +extern void static_zebra_vrf_register(struct vrf *vrf); +extern void static_zebra_vrf_unregister(struct vrf *vrf); + #endif diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py index 149a420a32..547a5949a3 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py @@ -11,16 +11,17 @@ for rtr in l3mdev_rtrs: rtrs = ['r1', 'r3', 'r4'] for rtr in rtrs: - luCommand(rtr, 'ip link show type vrf {}-cust1'.format(rtr),'cust1: .*UP,LOWER_UP','pass','VRF cust1 up') - luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'r..eth4: .*UP,LOWER_UP.* 192.168','pass','VRF cust1 IP config') + luCommand(rtr, 'ip link show type vrf {}-cust1'.format(rtr),'cust1: .*UP','pass','VRF cust1 intf up') + luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'r..eth4.*UP','pass','VRF cust1 IP intf up') + luCommand(rtr, 'ip add show vrf {}-cust1'.format(rtr),'192.168','pass','VRF cust1 IP config') luCommand(rtr, 'ip route show vrf {}-cust1'.format(rtr),'192.168...0/24 dev r.-eth','pass','VRF cust1 interface route') -luCommand('r4', 'ip link show type vrf r4-cust2','cust2: .*UP,LOWER_UP','pass','VRF cust2 up') -luCommand('r4', 'ip add show vrf r4-cust2','r..eth5.*UP,LOWER_UP.* 192.168','pass','VRF cust1 IP config') +luCommand('r4', 'ip link show type vrf r4-cust2','cust2: .*UP','pass','VRF cust2 up') +luCommand('r4', 'ip add show vrf r4-cust2','r..eth5.*UP.* 192.168','pass','VRF cust1 IP config') luCommand(rtr, 'ip route show vrf r4-cust2'.format(rtr),'192.168...0/24 dev r.-eth','pass','VRF cust2 interface route') rtrs = ['ce1', 'ce2', 'ce3'] for rtr in rtrs: luCommand(rtr, 'ip route show','192.168...0/24 dev ce.-eth0','pass','CE interface route') luCommand(rtr,'ping 192.168.1.1 -c 1',' 0. packet loss','wait','CE->PE ping') -luCommand('ce4', 'ip link show type vrf ce4-cust2','cust2: .*UP,LOWER_UP','pass','VRF cust2 up') +luCommand('ce4', 'ip link show type vrf ce4-cust2','cust2: .*UP','pass','VRF cust2 up') luCommand('ce4', 'ip route show vrf ce4-cust2','192.168...0/24 dev ce.-eth0','pass','CE interface route') luCommand('ce4','ping 192.168.2.1 -c 1 -I ce4-cust2',' 0. packet loss','wait','CE4->PE4 ping') diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref deleted file mode 100644 index fb193265be..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref +++ /dev/null @@ -1,31 +0,0 @@ -{ - "neighbors":[ - { - "2.2.2.2":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.1.2", - "ifaceName":"r1-eth1:10.0.1.1", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - }, - { - "3.3.3.3":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.2.3", - "ifaceName":"r1-eth2:10.0.2.1", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - } - ] -} - diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh deleted file mode 100644 index 7c4d0ab58c..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-no-neigh +++ /dev/null @@ -1,18 +0,0 @@ -{ - "2.2.2.2":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.1.2", - "ifaceName":"r1-eth1:10.0.1.1" - } - ], - "3.3.3.3":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.2.3", - "ifaceName":"r1-eth2:10.0.2.1" - } - ] -} diff --git a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist deleted file mode 100644 index 2270c3fdde..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r1/show_ip_ospf_neighbor.ref-old-nolist +++ /dev/null @@ -1,14 +0,0 @@ -{ - "2.2.2.2":{ - "priority":1, - "state":"Full/DR", - "address":"10.0.1.2", - "ifaceName":"r1-eth1:10.0.1.1" - }, - "3.3.3.3":{ - "priority":1, - "state":"Full/DR", - "address":"10.0.2.3", - "ifaceName":"r1-eth2:10.0.2.1" - } -} diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref deleted file mode 100644 index 1376579757..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref +++ /dev/null @@ -1,30 +0,0 @@ -{ - "neighbors":[ - { - "1.1.1.1":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.1.1", - "ifaceName":"r2-eth1:10.0.1.2", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - }, - { - "3.3.3.3":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.3.3", - "ifaceName":"r2-eth2:10.0.3.2", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - } - ] -} diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh deleted file mode 100644 index a982c1cbd3..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-no-neigh +++ /dev/null @@ -1,18 +0,0 @@ -{ - "1.1.1.1":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.1.1", - "ifaceName":"r2-eth1:10.0.1.2" - } - ], - "3.3.3.3":[ - { - "priority":1, - "state":"Full/DR", - "address":"10.0.3.3", - "ifaceName":"r2-eth2:10.0.3.2" - } - ] -} diff --git a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist deleted file mode 100644 index 18ffbc2f8a..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r2/show_ip_ospf_neighbor.ref-old-nolist +++ /dev/null @@ -1,14 +0,0 @@ -{ - "1.1.1.1":{ - "priority":1, - "state":"Full/Backup", - "address":"10.0.1.1", - "ifaceName":"r2-eth1:10.0.1.2" - }, - "3.3.3.3":{ - "priority":1, - "state":"Full/DR", - "address":"10.0.3.3", - "ifaceName":"r2-eth2:10.0.3.2" - } -} diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref deleted file mode 100644 index 41de304b2b..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref +++ /dev/null @@ -1,30 +0,0 @@ -{ - "neighbors":[ - { - "1.1.1.1":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.2.1", - "ifaceName":"r3-eth1:10.0.2.3", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - }, - { - "2.2.2.2":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.3.2", - "ifaceName":"r3-eth2:10.0.3.3", - "retransmitCounter":0, - "requestCounter":0, - "dbSummaryCounter":0 - } - ] - } - ] -} diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh deleted file mode 100644 index d7e0e42405..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-no-neigh +++ /dev/null @@ -1,18 +0,0 @@ -{ - "1.1.1.1":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.2.1", - "ifaceName":"r3-eth1:10.0.2.3" - } - ], - "2.2.2.2":[ - { - "priority":1, - "state":"Full/Backup", - "address":"10.0.3.2", - "ifaceName":"r3-eth2:10.0.3.3" - } - ] -} diff --git a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist b/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist deleted file mode 100644 index b0669742ab..0000000000 --- a/tests/topotests/ldp-vpls-topo1/r3/show_ip_ospf_neighbor.ref-old-nolist +++ /dev/null @@ -1,14 +0,0 @@ -{ - "1.1.1.1":{ - "priority":1, - "state":"Full/Backup", - "address":"10.0.2.1", - "ifaceName":"r3-eth1:10.0.2.3" - }, - "2.2.2.2":{ - "priority":1, - "state":"Full/Backup", - "address":"10.0.3.2", - "ifaceName":"r3-eth2:10.0.3.3" - } -} diff --git a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py index 0948c2e41b..ce651c50cd 100755 --- a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py +++ b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py @@ -144,9 +144,6 @@ def setup_module(mod): ) tgen.start_router() - for router in router_list.values(): - if router.has_version('<', '3'): - tgen.set_error('unsupported version') def teardown_module(mod): "Teardown the pytest environment" @@ -180,30 +177,8 @@ def test_ospf_convergence(): if tgen.routers_have_failure(): pytest.skip(tgen.errors) - # Old output (before FRR PR1383) didn't show a list of neighbors. - # Check for dict object and compare to old output if this is the case - tgen = get_topogen() - router = tgen.gears['r1'] - output = router.vtysh_cmd("show ip ospf neighbor json", isjson=True) - - # We could have either old format (without "neighbors" and direct list - # of IP's or new format from PR1659 with "neighbors". - # Trying old formats first and fall back to new format - # - # New format: neighbors have dict instead of list of dicts (PR1723). - if output.has_key('neighbors'): - if isinstance(output['neighbors'], dict): - reffile = "show_ip_ospf_neighbor.json" - else: - reffile = "show_ip_ospf_neighbor.ref" - else: - if isinstance(output["2.2.2.2"], dict): - reffile = "show_ip_ospf_neighbor.ref-old-nolist" - else: - reffile = "show_ip_ospf_neighbor.ref-no-neigh" - for rname in ['r1', 'r2', 'r3']: - router_compare_json_output(rname, "show ip ospf neighbor json", reffile) + router_compare_json_output(rname, "show ip ospf neighbor json", "show_ip_ospf_neighbor.json") def test_rib(): logger.info("Test: verify RIB") diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index a762e9555c..08126f6885 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -2422,6 +2422,53 @@ DEFUN (vtysh_show_error_code, return CMD_SUCCESS; } +/* Northbound. */ +DEFUN (show_yang_operational_data, + show_yang_operational_data_cmd, + "show yang operational-data XPATH$xpath\ + [{\ + format <json$json|xml$xml>\ + |translate WORD$translator_family\ + }]" DAEMONS_LIST, + SHOW_STR + "YANG information\n" + "Show YANG operational data\n" + "XPath expression specifying the YANG data path\n" + "Set the output format\n" + "JavaScript Object Notation\n" + "Extensible Markup Language\n" + "Translate operational data\n" + "YANG module translator\n" + DAEMONS_STR) +{ + int idx_protocol = argc - 1; + char *fcmd = argv_concat(argv, argc - 1, 0); + int ret = vtysh_client_execute_name(argv[idx_protocol]->text, fcmd); + XFREE(MTYPE_TMP, fcmd); + return ret; +} + +DEFUNSH(VTYSH_ALL, debug_nb, + debug_nb_cmd, + "[no] debug northbound\ + [<\ + callbacks$cbs [{configuration$cbs_cfg|state$cbs_state|rpc$cbs_rpc}]\ + |notifications$notifications\ + |events$events\ + >]", + NO_STR + DEBUG_STR + "Northbound debugging\n" + "Callbacks\n" + "Configuration\n" + "State\n" + "RPC\n" + "Notifications\n" + "Events\n") +{ + return CMD_SUCCESS; +} + /* Memory */ DEFUN (vtysh_show_memory, vtysh_show_memory_cmd, @@ -2548,10 +2595,11 @@ DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd, } DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd, - "no log facility [FACILITY]", NO_STR + "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]", + NO_STR "Logging control\n" "Reset syslog facility to default (daemon)\n" - "Syslog facility\n") + LOG_FACILITY_DESC) { return CMD_SUCCESS; } @@ -4017,6 +4065,11 @@ void vtysh_init_vty(void) install_element(ENABLE_NODE, &vtysh_debug_memstats_cmd); install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd); + /* northbound */ + install_element(VIEW_NODE, &show_yang_operational_data_cmd); + install_element(ENABLE_NODE, &debug_nb_cmd); + install_element(CONFIG_NODE, &debug_nb_cmd); + /* misc lib show commands */ install_element(VIEW_NODE, &vtysh_show_memory_cmd); install_element(VIEW_NODE, &vtysh_show_modules_cmd); diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang index 3313dc2f20..faa880eff4 100644 --- a/yang/frr-isisd.yang +++ b/yang/frr-isisd.yang @@ -61,6 +61,13 @@ module frr-isisd { "This type defines IS-IS level of an object."; } + typedef extended-circuit-id { + type uint32; + description + "This type defines the extended circuit ID + associated with an interface."; + } + typedef network-type { type enumeration { enum "unknown" { @@ -95,6 +102,20 @@ module frr-isisd { pattern, An example LSP ID is 0143.0438.AeF0.02-01"; } + typedef snpa { + type string { + length "0 .. 20"; + } + description + "This type defines the Subnetwork Point + of Attachment (SNPA) format. + The SNPA should be encoded according to the rules + specified for the particular type of subnetwork + being used. As an example, for an ethernet subnetwork, + the SNPA is encoded as a MAC address like + '00aa.bbcc.ddee'."; + } + typedef system-id { type string { pattern "[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}\\.[0-9A-Fa-f]{4}"; @@ -275,6 +296,399 @@ module frr-isisd { } } + grouping interface-config { + description "Interface configuration grouping"; + + leaf area-tag { + type string; + mandatory true; + description + "Area-tag associated to this circuit."; + } + + leaf ipv4-routing { + type boolean; + default "false"; + description + "Routing IS-IS IPv4 traffic over this circuit."; + } + + leaf ipv6-routing { + type boolean; + default "false"; + description + "Routing IS-IS IPv6 traffic over this circuit."; + } + + leaf circuit-type { + type level; + default "level-1-2"; + description + "IS-type of this circuit."; + } + + leaf bfd-monitoring { + type boolean; + default false; + description "Monitor IS-IS peers on this circuit."; + } + + container csnp-interval { + description + "Complete Sequence Number PDU (CSNP) generation interval."; + leaf level-1 { + type uint16 { + range "1..600"; + } + units "seconds"; + default "10"; + description + "CNSP interval for level-1"; + } + + leaf level-2 { + type uint16 { + range "1..600"; + } + units "seconds"; + default "10"; + description + "CNSP interval for level-2"; + } + } + + container psnp-interval { + description + "Partial Sequence Number PDU (PSNP) generation interval."; + leaf level-1 { + type uint16 { + range "1..120"; + } + units "seconds"; + default "2"; + description + "PNSP interval for level-1"; + } + + leaf level-2 { + type uint16 { + range "1..120"; + } + units "seconds"; + default "2"; + description + "PCNSP interval for level-2"; + } + } + + container hello { + description + "Parameters related to IS-IS hello PDUs."; + leaf padding { + type boolean; + default "true"; + description + "Add padding to IS-IS hello PDUs."; + } + + container interval { + description + "Interval between consecutive hello messages."; + leaf level-1 { + type uint32 { + range "1..600"; + } + units "seconds"; + default "3"; + description + "Holding time for level-1; interval will depend on multiplier."; + } + + leaf level-2 { + type uint32 { + range "1..600"; + } + units "seconds"; + default "3"; + description + "Holding time for level-2; interval will depend on multiplier."; + } + } + + container multiplier { + description + "Multiplier for the hello messages holding time."; + leaf level-1 { + type uint16 { + range "2..100"; + } + default "10"; + description + "Multiplier for the hello holding time."; + } + + leaf level-2 { + type uint16 { + range "2..100"; + } + default "10"; + description + "Multiplier for the hello holding time."; + } + } + } + + container metric { + description + "Default metric for this IS-IS circuit."; + leaf level-1 { + type uint32 { + range "0..16777215"; + } + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + default "10"; + description + "Default level-1 metric for this IS-IS circuit."; + } + + leaf level-2 { + type uint32 { + range "0..16777215"; + } + must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; + default "10"; + description + "Default level-2 metric for this IS-IS circuit."; + } + } + + container priority { + description + "Priority for Designated Router election."; + leaf level-1 { + type uint8 { + range "0..127"; + } + default "64"; + description + "Level-1 priority for this IS-IS circuit."; + } + + leaf level-2 { + type uint8 { + range "0..127"; + } + default "64"; + description + "Level-2 priority for this IS-IS circuit."; + } + } + + leaf network-type { + type network-type; + default "broadcast"; + must "(. = \"point-to-point\") or (. = \"broadcast\")"; + description + "Explicitly configured type of IS-IS circuit (broadcast or point-to-point)."; + } + + leaf passive { + type boolean; + default "false"; + description + "Interface is in passive mode."; + } + + container password { + presence "Present if a password is set for this IS interface."; + uses isis-password; + } + + leaf disable-three-way-handshake { + type boolean; + default "false"; + description + "Disables three-way handshake when creating new adjacencies."; + } + + container multi-topology { + description + "IS-IS topologies configured on this circuit."; + leaf ipv4-unicast { + type boolean; + default "true"; + description + "IPv4 unicast topology."; + } + + leaf ipv4-multicast { + type boolean; + default "true"; + description + "IPv4 multicast topology."; + } + + leaf ipv4-management { + type boolean; + default "true"; + description + "IPv4 management topology."; + } + + leaf ipv6-unicast { + type boolean; + default "true"; + description + "IPv6 unicast topology."; + } + + leaf ipv6-multicast { + type boolean; + default "true"; + description + "IPv6 multicast topology."; + } + + leaf ipv6-management { + type boolean; + default "true"; + description + "IPv6 management topology."; + } + + leaf ipv6-dstsrc { + type boolean; + default "true"; + description + "IPv6 destination-source topology."; + } + } + } + + grouping adjacency-state { + container adjacencies { + config false; + list adjacency { + leaf neighbor-sys-type { + type level; + description + "Level capability of neighboring system"; + } + leaf neighbor-sysid { + type system-id; + description + "The system-id of the neighbor"; + } + leaf neighbor-extended-circuit-id { + type extended-circuit-id; + description + "Circuit ID of the neighbor"; + } + leaf neighbor-snpa { + type snpa; + description + "SNPA of the neighbor"; + } + leaf hold-timer { + type uint16; + units seconds; + description + "The holding time in seconds for this + adjacency. This value is based on + received hello PDUs and the elapsed + time since receipt."; + } + leaf neighbor-priority { + type uint8 { + range "0 .. 127"; + } + description + "Priority of the neighboring IS for becoming + the DIS."; + } + leaf state { + type adj-state-type; + description + "This leaf describes the state of the interface."; + } + + description + "List of operational adjacencies."; + } + description + "This container lists the adjacencies of + the local node."; + } + description + "Adjacency state"; + } + + grouping event-counters { + container event-counters { + config false; + leaf adjacency-changes { + type uint32; + description + "The number of times an adjacency state change has + occurred on this interface."; + } + leaf adjacency-number { + type uint32; + description + "The number of adjacencies on this interface."; + } + leaf init-fails { + type uint32; + description + "The number of times initialization of this + interface has failed. This counts events such + as PPP NCP failures. Failures to form an + adjacency are counted by adjacency-rejects."; + } + leaf adjacency-rejects { + type uint32; + description + "The number of times an adjacency has been + rejected on this interface."; + } + leaf id-len-mismatch { + type uint32; + description + "The number of times an IS-IS PDU with an ID + field length different from that for this + system has been received on this interface."; + } + leaf max-area-addresses-mismatch { + type uint32; + description + "The number of times an IS-IS PDU has been + received on this interface with the + max area address field differing from that of + this system."; + } + leaf authentication-type-fails { + type uint32; + description + "Number of authentication type mismatches."; + } + leaf authentication-fails { + type uint32; + description + "Number of authentication key failures."; + } + description "IS-IS interface event counters."; + } + description + "Grouping for IS-IS interface event counters"; + } + + grouping interface-state { + description + "IS-IS interface operational state."; + uses adjacency-state; + uses event-counters; + } + grouping notification-instance-hdr { description "Instance specific IS-IS notification data grouping"; @@ -313,7 +727,7 @@ module frr-isisd { } leaf extended-circuit-id { - type uint32; + type extended-circuit-id; description "Eextended circuit-id of the interface."; } @@ -733,270 +1147,8 @@ module frr-isisd { presence "Present if an IS-IS circuit is defined for this interface."; description "IS-IS interface parameters."; - leaf area-tag { - type string; - mandatory true; - description - "Area-tag associated to this circuit."; - } - - leaf ipv4-routing { - type boolean; - default "false"; - description - "Routing IS-IS IPv4 traffic over this circuit."; - } - - leaf ipv6-routing { - type boolean; - default "false"; - description - "Routing IS-IS IPv6 traffic over this circuit."; - } - - leaf circuit-type { - type level; - default "level-1-2"; - description - "IS-type of this circuit."; - } - - leaf bfd-monitoring { - type boolean; - default false; - description "Monitor IS-IS peers on this circuit."; - } - - container csnp-interval { - description - "Complete Sequence Number PDU (CSNP) generation interval."; - leaf level-1 { - type uint16 { - range "1..600"; - } - units "seconds"; - default "10"; - description - "CNSP interval for level-1"; - } - - leaf level-2 { - type uint16 { - range "1..600"; - } - units "seconds"; - default "10"; - description - "CNSP interval for level-2"; - } - } - - container psnp-interval { - description - "Partial Sequence Number PDU (PSNP) generation interval."; - leaf level-1 { - type uint16 { - range "1..120"; - } - units "seconds"; - default "2"; - description - "PNSP interval for level-1"; - } - - leaf level-2 { - type uint16 { - range "1..120"; - } - units "seconds"; - default "2"; - description - "PCNSP interval for level-2"; - } - } - - container hello { - description - "Parameters related to IS-IS hello PDUs."; - leaf padding { - type boolean; - default "true"; - description - "Add padding to IS-IS hello PDUs."; - } - - container interval { - description - "Interval between consecutive hello messages."; - leaf level-1 { - type uint32 { - range "1..600"; - } - units "seconds"; - default "3"; - description - "Holding time for level-1; interval will depend on multiplier."; - } - - leaf level-2 { - type uint32 { - range "1..600"; - } - units "seconds"; - default "3"; - description - "Holding time for level-2; interval will depend on multiplier."; - } - } - - container multiplier { - description - "Multiplier for the hello messages holding time."; - leaf level-1 { - type uint16 { - range "2..100"; - } - default "10"; - description - "Multiplier for the hello holding time."; - } - - leaf level-2 { - type uint16 { - range "2..100"; - } - default "10"; - description - "Multiplier for the hello holding time."; - } - } - } - - container metric { - description - "Default metric for this IS-IS circuit."; - leaf level-1 { - type uint32 { - range "0..16777215"; - } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; - default "10"; - description - "Default level-1 metric for this IS-IS circuit."; - } - - leaf level-2 { - type uint32 { - range "0..16777215"; - } - must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'"; - default "10"; - description - "Default level-2 metric for this IS-IS circuit."; - } - } - - container priority { - description - "Priority for Designated Router election."; - leaf level-1 { - type uint8 { - range "0..127"; - } - default "64"; - description - "Level-1 priority for this IS-IS circuit."; - } - - leaf level-2 { - type uint8 { - range "0..127"; - } - default "64"; - description - "Level-2 priority for this IS-IS circuit."; - } - } - - leaf network-type { - type network-type; - default "broadcast"; - must "(. = \"point-to-point\") or (. = \"broadcast\")"; - description - "Explicitly configured type of IS-IS circuit (broadcast or point-to-point)."; - } - - leaf passive { - type boolean; - default "false"; - description - "Interface is in passive mode."; - } - - container password { - presence "Present if a password is set for this IS interface."; - uses isis-password; - } - - leaf disable-three-way-handshake { - type boolean; - default "false"; - description - "Disables three-way handshake when creating new adjacencies."; - } - - container multi-topology { - description - "IS-IS topologies configured on this circuit."; - leaf ipv4-unicast { - type boolean; - default "true"; - description - "IPv4 unicast topology."; - } - - leaf ipv4-multicast { - type boolean; - default "true"; - description - "IPv4 multicast topology."; - } - - leaf ipv4-management { - type boolean; - default "true"; - description - "IPv4 management topology."; - } - - leaf ipv6-unicast { - type boolean; - default "true"; - description - "IPv6 unicast topology."; - } - - leaf ipv6-multicast { - type boolean; - default "true"; - description - "IPv6 multicast topology."; - } - - leaf ipv6-management { - type boolean; - default "true"; - description - "IPv6 management topology."; - } - - leaf ipv6-dstsrc { - type boolean; - default "true"; - description - "IPv6 destination-source topology."; - } - } + uses interface-config; + uses interface-state; } } diff --git a/yang/frr-nexthop.yang b/yang/frr-nexthop.yang new file mode 100644 index 0000000000..00ba02a3c3 --- /dev/null +++ b/yang/frr-nexthop.yang @@ -0,0 +1,200 @@ +module frr-nexthop { + yang-version 1.1; + namespace "http://frrouting.org/yang/nexthop"; + prefix frr-nexthop; + + import ietf-inet-types { + prefix inet; + } + + import ietf-routing-types { + prefix rt-types; + } + + organization + "Free Range Routing"; + contact + "FRR Users List: <mailto:frog@lists.frrouting.org> + FRR Development List: <mailto:dev@lists.frrouting.org>"; + description + "This module defines a model for managing FRR nexthop information."; + + revision 2019-08-15 { + description + "Initial revision."; + } + + typedef gateway-address { + type inet:ip-address; + } + + typedef nexthop-type { + type enumeration { + enum "ifindex" { + value 1; + description + "Specific interface."; + } + enum "ip4" { + value 2; + description + "IPv4 address."; + } + enum "ip4-ifindex" { + value 3; + description + "IPv4 address and interface."; + } + enum "ip6" { + value 4; + description + "IPv6 address."; + } + enum "ip6-ifindex" { + value 5; + description + "IPv6 address and interface."; + } + enum "blackhole" { + value 6; + description + "Unreachable or prohibited."; + } + } + description + "Nexthop types."; + } + + typedef blackhole-type { + type enumeration { + enum "unspec" { + value 0; + description + "Generic unreachable."; + } + enum "null" { + value 1; + description + "Null type."; + } + enum "reject" { + value 2; + description + "ICMP unreachable."; + } + enum "prohibited" { + value 3; + description + "ICMP admin-prohibited."; + } + } + default "null"; + description + "Nexthop blackhole types."; + } + + /* + * Nexthop object + */ + grouping frr-nexthop { + leaf nh-type { + type nexthop-type; + mandatory true; + description + "The nexthop type."; + } + + leaf gateway { + type gateway-address; + description + "The nexthop gateway address."; + } + + leaf vrf { + type string; + description + "The nexthop vrf name, if different from the route."; + } + + leaf interface { + type string; + description + "The nexthop egress interface."; + } + + leaf bh-type { + type blackhole-type; + description + "A blackhole sub-type, if the nexthop is a blackhole type."; + } + + leaf flags { + type uint32; + description + "The nexthop's raw flags value."; + } + + leaf is-duplicate { + type empty; + description + "Duplicate nexthop; will be ignored."; + } + leaf is-recursive { + type empty; + description + "Nexthop must be resolved through another gateway."; + } + leaf is-onlink { + type empty; + description + "Nexthop is directly connected."; + } + leaf is-active { + type empty; + description + "Nexthop is active."; + } + + uses rt-types:mpls-label-stack { + description + "Nexthop's MPLS label stack."; + } + + leaf mtu { + type uint32; + description + "The nexthop's specific MTU."; + } + + } // End of nexthop + + /* + * Nexthop-group container + */ + grouping frr-nexthop-group { + description + "A nexthop-group, represented as a list of nexthop objects."; + + leaf name { + type string; + description + "The nexthop-group name."; + } + + list entry { + key "id"; + description + "A list of nexthop objects."; + leaf id { + type uint32; + description + "Identifies a nexthop within a nexthop group; the entries + are ordered by id value, and the value has no other meaning."; + } + + uses frr-nexthop; + + } + } // End of frr-nexthop-group + +} diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang new file mode 100644 index 0000000000..b5ca5c9a40 --- /dev/null +++ b/yang/frr-zebra.yang @@ -0,0 +1,1788 @@ +module frr-zebra { + yang-version 1.1; + namespace "http://frrouting.org/yang/zebra"; + prefix frr-zebra; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import frr-route-types { + prefix frr-route-types; + } + + import ietf-routing-types { + prefix rt-types; + } + + import frr-nexthop { + prefix frr-nh; + } + + import frr-interface { + prefix frr-interface; + } + + organization + "Free Range Routing"; + contact + "FRR Users List: <mailto:frog@lists.frrouting.org> + FRR Development List: <mailto:dev@lists.frrouting.org>"; + description + "This module defines a model for managing the FRR zebra daemon."; + + revision 2019-06-01 { + description + "Initial revision."; + } + + typedef unix-timestamp { + type uint32; + units "seconds"; + description + "An absolute time in seconds since the unix epoch."; + } + + /* + * Multicast RPF mode configurable type + */ + typedef mcast-rpf-lookup-mode { + type enumeration { + enum "none" { + value 0; + description + "No mode set."; + } + enum "mrib-only" { + value 1; + description + "Lookup in unicast RIB only."; + } + enum "urib-only" { + value 2; + description + "Lookup in multicast RIB only."; + } + enum "mrib-then-urib" { + value 3; + description + "Try multicast RIB first, fall back to unicast RIB."; + } + enum "lower-distance" { + value 4; + description + "Lookup both unicast and mcast, use entry with lower distance."; + } + enum "longer-prefix" { + value 5; + description + "Lookup both unicast and mcast, use entry with longer prefix."; + } + } + description + "Multicast RPF lookup behavior"; + } + + /* + * Common route data, shared by v4 and v6 routes. + */ + grouping route-common { + description + "Common information about a route."; + + leaf vrf { + type string; + description + "The route's vrf name."; + } + + leaf distance { + type uint8; + description + "Admin distance based on routing protocol."; + } + leaf metric { + type uint32; + description + "Route metric value."; + } + leaf tag { + type uint32 { + range "1..4294967295"; + } + description + "Route tag value."; + } + + leaf is-selected { + type empty; + description + "Route is the selected or preferred route for the prefix."; + } + leaf is-installed { + type empty; + description + "Route is installed in the FIB."; + } + leaf is-failed { + type empty; + description + "Route installation in FIB has failed."; + } + leaf is-queued { + type empty; + description + "Route has a pending FIB operation that has not completed."; + } + + leaf internal-flags { + type int32; + description + "Internal flags for the route."; + } + leaf internal-status { + type int32; + description + "Internal status for the route."; + } + + leaf uptime { + type uint32; + units "seconds"; + description + "Uptime for the route."; + } + + container nexthop-group { + description + "Nexthop information for the route."; + + uses frr-nh:frr-nexthop-group; + } + + } // End of route-common + + /* + * IPv4 Route object. + */ + grouping ip4-route { + description + "An IPv4 route."; + + leaf prefix { + type inet:ipv4-prefix; + description + "IP address (in the form A.B.C.D) and prefix length, + separated by the slash (/) character. The range of + values for the prefix-length is 0 to 32."; + } + leaf "protocol" { + type frr-route-types:frr-route-types-v4; + description + "The protocol owning the route."; + } + + uses route-common; + + } // End of ip4-route + + /* + * IPv6 Route object. + */ + grouping ip6-route { + description + "An IPv6 route."; + + leaf prefix { + type inet:ipv6-prefix; + description + "The route's IPv6 prefix."; + } + leaf "protocol" { + type frr-route-types:frr-route-types-v6; + description + "The protocol owning the route."; + } + + uses route-common; + + } // End of ip6-route + + /* + * VxLAN Network Identifier type + */ + typedef vni-id-type { + type uint32 { + range "0..16777215"; + } + description + "A VxLAN network identifier value."; + } + + typedef vni-vtep-flood-type { + type enumeration { + enum "head-end-repl" { + value 0; + description + "Head-end replication."; + } + enum "disabled" { + value 1; + description + "Flooding disabled."; + } + enum pim-sm { + value 2; + description + "Multicast PIM-SM."; + } + } + } + + /* + * Information about EVPN VNIs + */ + grouping vni-information { + choice type-choice { + case l2 { + leaf is-layer2 { + type empty; + description + "Information about an L2 VNI."; + } + leaf vtep-count { + type uint32; + description + "Number of VTEPs."; + } + } + case l3 { + leaf is-layer3 { + type empty; + description + "Information about an L3 VNI."; + } + } + } + leaf vni-id { + type vni-id-type; + description + "The VNI identifier."; + } + leaf vxlan-ifname { + type frr-interface:interface-ref; + description + "The VxLAN interface name."; + } + leaf mac-count { + type uint32; + description + "Number of valid MACs."; + } + leaf neighbor-count { + type uint32; + description + "Number of neighbors."; + } + leaf vrf { + type string; + description + "The tenant VRF."; + } + leaf local-vtep-addr { + type inet:ipv4-address; + description + "The local VTEP IP address."; + } + } + + /* + * Detailed EVPN VNI information for L2. + */ + grouping vni-l2-detail { + leaf if-index { + type uint32; + description + "The VxLAN ifindex."; + } + leaf advertise-gw { + type empty; + description + "The gateway MAC-IP is being advertised."; + } + leaf mcase-group { + type rt-types:ipv4-multicast-group-address; + description + "The VNI multicast group for BUM traffic."; + } + list remote-vtep-list { + leaf remote-vtep { + type inet:ipv4-address; + description + "The remote VTEP IP address."; + } + leaf vtep-flood { + type vni-vtep-flood-type; + } + } + } + + /* + * Detailed EVPN VNI information for L3. + */ + grouping vni-l3-detail { + leaf svi-interface { + type string; + description + "The SVI interface."; + } + leaf is-up { + type empty; + description + "The state is active."; + } + leaf prefix-only { + type empty; + description + "Prefix routes only"; + } + leaf router-mac { + type yang:mac-address; + description + "The VNI Router MAC address."; + } + list vni-list { + description + "A list of the associated L2 VNIs."; + leaf vni-id { + type vni-id-type; + description + "An L2 VNI identifier."; + } + } + } + + /* + * Debug options + */ + grouping zebra-debugs { + leaf debug-events { + type boolean; + description "Debug ZAPI events."; + } + leaf debug-zapi-send { + type boolean; + description "Debug ZAPI messages sent."; + } + leaf debug-zapi-recv { + type boolean; + description "Debug ZAPI messages received."; + } + leaf debug-zapi-detail { + type boolean; + description "Debug ZAPI details."; + } + leaf debug-kernel { + type boolean; + description "Debug kernel events."; + } + leaf debug-kernel-msg-send { + type boolean; + description "Debug kernel messages sent."; + } + leaf debug-kernel-msg-recv { + type boolean; + description "Debug kernel messages received."; + } + leaf debug-rib { + type boolean; + description "Debug RIB processing."; + } + leaf debug-rib-detail { + type boolean; + description "Debug RIB processing details."; + } + leaf debug-fpm { + type boolean; + description "Debug the FIB Push Interface subsystem."; + } + leaf debug-nht { + type boolean; + description "Debug Nexthop-tracking."; + } + leaf debug-nht-detail { + type boolean; + description "Debug Nexthop-tracking details."; + } + leaf debug-mpls { + type boolean; + description "Debug MPLS."; + } + leaf debug-vxlan { + type boolean; + description "Debug VxLAN."; + } + leaf debug-pw { + type boolean; + description "Debug pseudowires."; + } + leaf debug-dplane { + type boolean; + description "Debug the dataplane subsystem."; + } + leaf debug-dplane-detail { + type boolean; + description "Debug dataplane subsystem details."; + } + leaf debug-mlag { + type boolean; + description "Debug MLAG."; + } + } + + /* + * Main zebra container + */ + container zebra { + description + "Data model for the Zebra daemon."; + + leaf mcast-rpf-lookup { + type frr-zebra:mcast-rpf-lookup-mode; + default "mrib-then-urib"; + description + "Multicast RPF lookup behavior."; + } + + leaf ip-forwarding { + type boolean; + description + "IP forwarding status."; + } + + leaf ipv6-forwarding { + type enumeration { + enum "unknown" { + value -1; + description + "Unknown state."; + } + enum "off" { + value 0; + description + "IPv6 forwarding disabled."; + } + enum "on" { + value 1; + description + "IPv6 forwarding enabled."; + } + } + description + "IPv6 forwarding status."; + } + + leaf workqueue-hold-timer { + type uint32 { + range "0..10000"; + } + units "milliseconds"; + default "10"; + description + "Work-queue processing hold timer, in milliseconds."; + } + + leaf zapi-packets { + type uint32 { + range "1..10000"; + } + default "1000"; + description + "Number of ZAPI packets to process before relinquishing + the main thread."; + } + + container import-kernel-table { + description + "Parameters to use when importing IPv4 routes from a non-main kernel + routing table."; + + leaf table-id { + type uint32 { + range "1..252"; + } + description + "The kernel table id."; + } + leaf distance { + type uint32 { + range "1..255"; + } + default "15"; + description + "The admin distance to use for imported routes."; + } + leaf route-map { + type string; + description + "A route-map to filter imported routes."; + } + } + + leaf allow-external-route-update { + type empty; + description + "Allow FRR-controlled routes to be overwritten by external processes"; + } + + leaf dplane-queue-limit { + type uint32 { + range "0..10000"; + } + default "200"; + description + "Limit on the number of updates queued to the dataplane subsystem."; + } + + list vrf-vni-mapping { + description + "EVPN VNI mapping corresponding to a VRF."; + key "vrf-id"; + leaf vrf-id { + type uint32; + description + "The identifier for a VRF."; + } + leaf vni-id { + type vni-id-type; + description + "The VNI id to map to the VRF."; + } + leaf prefix-only { + type empty; + description + "Prefix routes only."; + } + } + + /* + * Debug options + */ + container debugs { + uses zebra-debugs; + } /* End of debugs */ + + /* + * End of configuration attributes + */ + + /* + * Operational data. + */ + container state { + config false; + description + "Operational data."; + + } // End of operational / state container + + } // End of zebra container + + /* + * RPCs + */ + rpc get-route-information { + description + "Retrieve IPv4 or IPv6 unicast routes."; + + input { + + choice ip-type { + case v4 { + leaf ipv4 { + type empty; + mandatory true; + description + "Retrieve IPv4 routes."; + } + leaf prefix-v4 { + type inet:ipv4-prefix; + description + "Retrieve routes matching a specific prefix."; + } + leaf supernets-only { + type empty; + description + "Skip routes that are subnets of classful prefix sizes."; + } + } + case v6 { + leaf ipv6 { + type empty; + mandatory true; + description + "Retrieve IPv6 routes."; + } + leaf prefix-v6 { + type inet:ipv6-prefix; + description + "Retrieve routes matching a specific prefix."; + } + } + } + + choice vrf-choice { + case single { + leaf vrf { + type string; + description + "Retrieve routes in a non-default vrf."; + } + } + case all { + leaf all-vrfs { + type empty; + description + "Retrieve routes from all vrfs."; + } + } + } + + leaf fib-routes { + type empty; + description + "Retrieve FIB routes rather than RIB routes."; + } + + leaf table-id { + type uint32 { + range "1..4294967295"; + } + description + "Routing table id to retrieve."; + } + + leaf protocol { + type frr-route-types:frr-route-types-v4; + description + "Retrieve routes from a specific protocol daemon."; + } + leaf ospf-instance { + type uint32 { + range "1..65535"; + } + must '../protocol = "ospf"'; + description + "Retrieve routes from a specific OSPF instance."; + } + + choice detail { + case det { + leaf include-detail { + type empty; + description + "Include detailed information."; + } + } + case summ { + leaf summary { + type empty; + description + "Include summary information only."; + } + } + } + } // End of input + + output { + choice route-list { + case v4 { + container routes-v4 { + description + "IPv4 route information."; + list route { + uses ip4-route; + } + } + } + case v6 { + container routes-v6 { + description + "IPv6 route information."; + list route { + uses ip6-route; + } + } + } + } + } // End of output + + } // End get-route-information + + rpc get-v6-mroute-info { + description + "Retrieve IPv6 multicast routes."; + + input { + choice vrf-choice { + case single { + leaf vrf { + type string; + description + "Retrieve routes in a non-default vrf."; + } + } + case all { + leaf all-vrfs { + type empty; + description + "Retrieve routes from all vrfs."; + } + } + } + } + + output { + container routes { + description + "IPv6 mcast route information."; + list route { + uses ip6-route; + } + } + } + + }// End get-v6-mroute-info + + + rpc get-vrf-info { + description + "Retrieve VRF information; the default VRF is elided."; + + // Note: no input clause. + + output { + list vrf-list { + leaf name { + type string; + description + "The VRF name"; + } + leaf is-user-config { + type empty; + description + "The VRF was configured by an admin."; + } + leaf vrf-id { + type uint32; + description + "The VRF id."; + } + choice vrf-type { + case inactive { + leaf is-inactive { + type empty; + description + "The VRF is inactive."; + } + } + case netns { + leaf netns-name { + type string; + description + "The net namespace name associated with the VRF."; + } + } + case table { + leaf table-id { + type uint32; + description + "The table-id associated with the VRF."; + } + } + } + } + } + } // End get-vrf-info + + rpc get-vrf-vni-info { + description + "Retrieve mappings between EVPN VNI and VRF."; + + // Note: no input clause. + + output { + list vrf-vni-list { + leaf vrf-name { + type string; + description + "The VRF name."; + } + leaf vni-id { + type vni-id-type; + description + "The EVPN VNI."; + } + leaf vxlan-if-name { + type frr-interface:interface-ref; + description + "The VxLAN interface name."; + } + leaf svi-if-name { + type frr-interface:interface-ref; + description + "The SVI interface name."; + } + leaf router-mac-addr { + type yang:mac-address; + description + "Router MAC address."; + } + leaf is-up { + type empty; + description + "The state is active."; + } + } + } + } // End get-vrf-vni-info + + rpc get-evpn-info { + description + "Retrieve global information about EVPN."; + + // Note: No input clause. + + output { + leaf l2vni-count { + type uint32; + description + "Number of L2 VNIs."; + } + leaf l3vni-count { + type uint32; + description + "Number of L3 VNIs."; + } + leaf advertise-gateway { + type empty; + description + "Advertise the gateway MAC-IP."; + } + leaf advertise-svi { + type empty; + description + "Advertise SVI MAC-IP."; + } + leaf dup-detect { + type empty; + description + "Duplicate address detection is enabled."; + } + leaf dad-max-moves { + type uint32; + description + "Maximum moves allowed before address is considered duplicate."; + } + leaf dad-timeout { + type uint32; + units "seconds"; + description + "Duplicate address detection timeout."; + } + leaf dad-freeze { + type empty; + description + "Duplicate address detection freeze enabled."; + } + + choice dad-freeze-choice { + case freeze-permanent { + leaf dad-freeze-perm { + type empty; + description + "Duplicate address detection freeze is permanent."; + } + } + case freeze-time { + leaf dad-freeze-time { + type uint32; + units "seconds"; + description + "Duplicate address detection freeze timer."; + } + } + } + } + } // End get-evpn-info + + rpc get-vni-info { + // If no vni is specified, retrieve global list. + input { + choice vni-choice { + default "all-vnis"; + case all-vnis { + leaf all-vnis { + type empty; + description + "Retrieve information about all VNIs."; + } + } + case single-vni { + leaf vni-id { + type vni-id-type; + description + "Retrieve information about a specific EVPN VNI."; + } + } + } + leaf detailed-info { + type empty; + description + "Retrieve detailed information."; + } + } + + output { + list vni-list { + description + "Information about EVPN VNI objects."; + + uses vni-information; + + choice detail-choice { + case l2 { + description + "Detailed L2 information."; + uses vni-l2-detail; + } + case l3 { + description + "Detailed L3 information."; + uses vni-l3-detail; + } + } + } + } + } // End get-vni-info + + rpc get-evpn-vni-rmac { + description + "Retrieve information about VxLAN VNI RMACs."; + + input { + choice vni-choice { + default "all-vnis"; + case all-vnis { + leaf all-vnis { + type empty; + description + "Retrieve information about all VNIs."; + } + } + case single-vni { + leaf vni-id { + type vni-id-type; + description + "Retrieve information about a specific EVPN VNI."; + } + leaf vni-rmac { + type yang:mac-address; + description + "A single RMAC address."; + } + } + } + } + + output { + list rmac-info-list { + leaf rmac { + type yang:mac-address; + description + "The RMAC address."; + } + leaf remote-vtep { + type inet:ipv4-address; + description + "The remote VTEP IP address."; + } + leaf refcount { + type uint32; + description + "The refcount of the RMAC."; + } + list prefix-list { + leaf prefix-item { + type inet:ip-prefix; + description + "IP prefixes associated with the RMAC."; + } + } + } + } + } // End get-evpn-vni-rmac + + rpc get-evpn-vni-nexthops { + description + "Retrieve information about EVPN nexthops."; + + input { + choice vni-choice { + default "all-vnis"; + case all-vnis { + leaf all-vnis { + type empty; + description + "Retrieve information about all VNIs."; + } + } + case single-vni { + leaf vni-id { + type vni-id-type; + description + "Retrieve information about a specific EVPN VNI."; + } + leaf vni-ipaddr { + type inet:ip-address; + description + "A single host IP address (v4 or v6)."; + } + } + } + } + + output { + list nh-info-list { + leaf ip-addr { + type inet:ip-address; + description + "The nexthop IP address."; + } + leaf mac-addr { + type yang:mac-address; + description + "The nexthop MAC address."; + } + leaf refcount { + type uint32; + description + "The refcount of the RMAC."; + } + list prefix-list { + leaf prefix-item { + type inet:ip-prefix; + description + "IP prefixes associated with the RMAC."; + } + } + } + } + } // End get-evpn-vni-vteps + + rpc clear-evpn-dup-addr { + description + "Clear duplicate address detection state for one or all VNIs."; + input { + choice clear-dup-choice { + case all-case { + leaf all-vnis { + type empty; + description + "Clear all VNIs."; + } + } + case single-case { + leaf vni-id { + type vni-id-type; + description + "Clear state for a single EVPN VNI."; + } + choice ip-mac-choice { + description + "Clear state for a specific MAC or IP address."; + case ip-case { + leaf vni-ipaddr { + type inet:ip-address; + description + "A specific IP address (v4 or v6)."; + } + } + case mac-case { + leaf mac-addr { + type yang:mac-address; + description + "A specific MAC address."; + } + } + } + } + } + } + } // End clear-evpn-dup-addr + + rpc get-evpn-macs { + description + "Retrieve information about EVPN MAC addresses."; + input { + choice all-choice { + default "all-vni"; + + case all-vni { + leaf all-vnis { + type empty; + description + "Retrieve information for all VNIs."; + } + choice all-choices { + case detail-case { + leaf all-detail { + type empty; + description + "Include detailed results."; + } + } + case vtep-case { + leaf all-vtep-addr { + type inet:ipv4-address; + description + "A single VTEP address."; + } + } + case dup-case { + leaf all-dup { + type empty; + description + "Show duplicate addresses."; + } + } + } + } + case single-vni { + leaf vni-id { + type vni-id-type; + description + "Retrieve information for a single VNI."; + } + choice single-choices { + case detail-case { + leaf single-detail { + type empty; + description + "Include detailed results."; + } + } + case mac-case { + leaf single-mac { + type yang:mac-address; + description + "A specific MAC address."; + } + } + case vtep-case { + leaf single-vtep { + type inet:ipv4-address; + description + "A single VTEP address."; + } + } + case dup-case { + leaf single-dup { + type empty; + description + "Show duplicate addresses."; + } + } + } + } + } + } // End of input section + + output { + list mac-list { + leaf mac-addr { + type yang:mac-address; + description + "The MAC address."; + } + leaf vni { + type vni-id-type; + description + "The VNI value."; + } + leaf local-sequence { + type uint32; + description + "Local sequence number."; + } + leaf remote-sequence { + type uint32; + description + "Remote sequence number."; + } + leaf dad-count { + type uint32; + description + "Duplicate detection counter."; + } + leaf is-duplicate { + type empty; + description + "Duplicate MAC detected."; + } + leaf dup-detect-time { + type unix-timestamp; + description + "If a duplicate, the detection time."; + } + container dup-detect-started { + leaf dup-detect-start { + type unix-timestamp; + description + "Duplicate detection process start time."; + } + leaf dup-count { + type uint32; + description + "Duplicate detection count."; + } + } + + leaf is-auto { + type empty; + description + "This is an Auto MAC."; + } + leaf is-sticky { + type empty; + description + "This is a sticky MAC."; + } + leaf is-default-gw { + type empty; + description + "This is a default-gateway MAC."; + } + leaf is-remote-gw { + type empty; + description + "This is a remote-gateway MAC."; + } + list neighbor-list { + leaf neighbor-addr { + type inet:ip-address; + description + "Neighbor address."; + } + leaf is-active { + type empty; + description + "Neighbor is active."; + } + } + + leaf mac-count { + type uint32; + description + "Number of MACs (local and remote)."; + } + choice local-rem-choice { + case local-case { + leaf intf { + type frr-interface:interface-ref; + description + "The local interface name."; + } + leaf vlan { + type uint32; + description + "A VLAN id."; + } + } + case remote-case { + leaf vtep-addr { + type inet:ipv4-address; + description + "The remote VTEP IP address."; + } + } + } + } + } + } // End get-evpn-macs + + rpc get-evpn-arp-cache { + description + "Retrieve information about EVPN neighbor cache entries."; + input { + choice all-choice { + default "all-vni"; + + case all-vni { + leaf all-vnis { + type empty; + description + "Retrieve information for all VNIs."; + } + choice all-choices { + case detail-case { + leaf all-detail { + type empty; + description + "Include detailed results."; + } + } + case dup-case { + leaf all-dup { + type empty; + description + "Show duplicates."; + } + } + } + } + case single-vni { + leaf vni-id { + type vni-id-type; + description + "Retrieve information for a single VNI."; + } + choice single-choices { + case vtep-case { + leaf single-vtep { + type inet:ipv4-address; + description + "A single VTEP address."; + } + } + case neighbor-case { + leaf neighbor-addr { + type inet:ip-address; + description + "A single neighbor address."; + } + } + case dup-case { + leaf single-dup { + type empty; + description + "Show duplicates."; + } + } + } + } + } + } // End input section + + output { + list vni-list { + container vni-container { + description + "Information for one VNI."; + leaf vni-id { + type vni-id-type; + description + "The VNI id."; + } + list neigh-list { + description + "Information about a VNI's neighbor cache."; + + leaf mac-addr { + type yang:mac-address; + description + "A neighbor MAC address."; + } + leaf ip-addr { + type inet:ip-address; + description + "A neighbor IP address."; + } + leaf state-active { + type empty; + description + "Indicates whether the entry is active."; + } + + choice local-remote-choice { + case local-case { + leaf is-local { + type empty; + description + "The entry is local."; + } + } + case remote-case { + leaf is-remote { + type empty; + description + "The entry is remote."; + } + } + } + + leaf is-dup { + type empty; + description + "The entry is a detected duplicate."; + } + leaf is-default-gw { + type empty; + description + "The entry is a default gateway."; + } + leaf is-router { + type empty; + description + "The entry is a router."; + } + leaf local-sequence { + type uint32; + description + "The local sequence number."; + } + leaf remote-sequence { + type uint32; + description + "The remote sequence number."; + } + leaf remote-vtep { + type inet:ipv4-address; + description + "The remote VTEP address."; + } + } + } + } + } + } // End get-evpn-arp-cache + + rpc get-pbr-ipset { + input { + leaf name { + type string; + description + "An optional specific IPset name."; + } + } + + output { + list ipset-list { + leaf name { + type string; + description + "The IPset name."; + } + leaf ipset-type { + type enumeration { + enum "net-net" { + value 1; + description + ""; + } + enum "net-port-net" { + value 2; + description + ""; + } + enum "net-port" { + value 3; + description + ""; + } + enum "net" { + value 4; + description + ""; + } + } + } + leaf src-prefix { + type inet:ip-prefix; + description + ""; + } + leaf dest-prefix { + type inet:ip-prefix; + description + ""; + } + leaf src-port { + type inet:port-number; + description + ""; + } + leaf dest-port { + type inet:port-number; + description + ""; + } + + choice proto-choice { + description + "Filter UDP/TCP only, or a specific protocol number."; + case udp-tcp-case { + leaf is-udp-tcp { + type empty; + description + "Filter TCP/UDP ports only."; + } + } + case proto-case { + leaf proto { + type uint32; + description + "Filter a specific protocol number."; + } + } + } + container icmp-info { + description + "Additional information for ICMP filters."; + leaf type-min { + type uint8; + description + ""; + } + leaf type-max { + type uint8; + description + ""; + } + leaf code-min { + type uint8; + description + ""; + } + leaf code-max { + type uint8; + description + ""; + } + } + container ipset-stats { + leaf is-unique { + type empty; + description + ""; + } + leaf packet-counter { + type uint64; + description + ""; + } + leaf bytes-counter { + type uint64; + description + ""; + } + } + } + } + } // End get-pbr-ipset + + rpc get-pbr-iptable { + input { + leaf name { + type string; + description + "An optional single IPtable name."; + } + } + + output { + list iptable-list { + leaf name { + type string; + description + "The IPtable name."; + } + leaf unique-val { + type uint32; + description + ""; + } + choice action-choice { + description "The table action."; + case drop-case { + leaf action-drop { + type empty; + description ""; + } + } + case redirect-case { + leaf action-redirect { + type empty; + description ""; + } + } + } + leaf min-packet { + type uint32; + description + ""; + } + leaf max-packet { + type uint32; + description + ""; + } + leaf lookup-src-port { + type empty; + description + ""; + } + leaf lookup-dst-port { + type empty; + description + ""; + } + leaf tcp-flags { + type uint16; + description + ""; + } + leaf tcp-flags-mask { + type uint16; + description + ""; + } + leaf protocol-val { + type uint32; + description "An IP protocol number."; + } + container dscp-info { + leaf dscp-value { + type uint32; + description + "A DSCP value to match."; + } + leaf invert-match { + type empty; + description + "If set, exclude the specified value"; + } + } + container fragment-info { + leaf fragment-val { + type uint32; + description "An IP fragment value."; + } + leaf invert-match { + type empty; + description + "If set, exclude the specified value."; + } + } + container iptable-stats { + leaf packet-counter { + type uint64; + description + ""; + } + leaf bytes-counter { + type uint64; + description + ""; + } + } + container rule-info { + description + "Information about a rule, for redirect tables."; + leaf table-id { + type uint32; + description + "The rule table id."; + } + leaf table-fwmark { + type uint32; + description + "The firewall mark for the rule."; + } + } + } + } + } // End get-pbr-iptable + + /* + * Handy 'all-at-once' api to retrieve debugs + */ + rpc get-debugs { + output { + uses zebra-debugs; + } + } // End get-debugs + + augment "/frr-interface:lib/frr-interface:interface" { + description + "Extends interface model with Zebra-related parameters."; + container zebra { + list ip4-addr-list { + description + "IPv4 prefixes for an interface."; + key "ip4-prefix"; + leaf ip4-prefix { + type inet:ipv4-prefix; + description + "IPv4 address prefix."; + } + leaf ip4-peer { + type inet:ipv4-prefix; + description + "Peer prefix, for peer-to-peer interfaces."; + } + leaf label { + type string; + description + "Optional string label for the address."; + } + } + list ip6-addr-list { + description + "IPv6 prefixes for an interface."; + key "ip6-prefix"; + leaf ip6-prefix { + type inet:ipv6-prefix; + description + "IPv6 address prefix."; + } + leaf label { + type string; + description + "Optional string label for the address."; + } + } + + leaf multicast { + type boolean; + description + "Multicast flag for the interface."; + } + leaf link-detect { + type boolean; + description + "Link-detection for the interface."; + } + leaf shutdown { + type boolean; + description + "Interface admin status."; + } + leaf bandwidth { + type uint32 { + range "1..100000"; + } + description + "Link bandwidth informational parameter, in megabits."; + } + + // TODO -- link-params for (experimental/partial TE use in IGP extensions) + + } + } // End interface model augmentation + +} diff --git a/zebra/connected.c b/zebra/connected.c index 6b92945c63..87cf8c8f20 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -385,7 +385,7 @@ void connected_down(struct interface *ifp, struct connected *ifc) return; break; default: - zlog_info("Unknown AFI: %s", afi2str(afi)); + zlog_warn("Unknown AFI: %s", afi2str(afi)); break; } diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c71b95f753..59ab8c9d33 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -365,7 +365,7 @@ static void netlink_vrf_change(struct nlmsghdr *h, struct rtattr *tb, } } -static int get_iflink_speed(struct interface *interface) +static int get_iflink_speed(struct interface *interface, int *error) { struct ifreq ifdata; struct ethtool_cmd ecmd; @@ -373,6 +373,8 @@ static int get_iflink_speed(struct interface *interface) int rc; const char *ifname = interface->name; + if (error) + *error = 0; /* initialize struct */ memset(&ifdata, 0, sizeof(ifdata)); @@ -393,6 +395,9 @@ static int get_iflink_speed(struct interface *interface) if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Failure to read interface %s speed: %d %s", ifname, errno, safe_strerror(errno)); + /* no vrf socket creation may probably mean vrf issue */ + if (error) + *error = -1; return 0; } /* Get the current link state for the interface */ @@ -404,6 +409,9 @@ static int get_iflink_speed(struct interface *interface) zlog_debug( "IOCTL failure to read interface %s speed: %d %s", ifname, errno, safe_strerror(errno)); + /* no device means interface unreachable */ + if (errno == ENODEV && error) + *error = -1; ecmd.speed_hi = 0; ecmd.speed = 0; } @@ -413,9 +421,9 @@ static int get_iflink_speed(struct interface *interface) return (ecmd.speed_hi << 16) | ecmd.speed; } -uint32_t kernel_get_speed(struct interface *ifp) +uint32_t kernel_get_speed(struct interface *ifp, int *error) { - return get_iflink_speed(ifp); + return get_iflink_speed(ifp, error); } static int netlink_extract_bridge_info(struct rtattr *link_data, @@ -696,7 +704,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; - ifp->speed = get_iflink_speed(ifp); + ifp->speed = get_iflink_speed(ifp, NULL); ifp->ptm_status = ZEBRA_PTM_STATUS_UNKNOWN; /* Set zebra interface type */ @@ -1032,7 +1040,8 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* addr is primary key, SOL if we don't have one */ if (addr == NULL) { - zlog_debug("%s: NULL address", __func__); + zlog_debug("%s: Local Interface Address is NULL for %s", + __func__, ifp->name); return -1; } diff --git a/zebra/interface.c b/zebra/interface.c index 6486c01430..a724006e27 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -70,10 +70,19 @@ static int if_zebra_speed_update(struct thread *thread) struct zebra_if *zif = ifp->info; uint32_t new_speed; bool changed = false; + int error = 0; zif->speed_update = NULL; - new_speed = kernel_get_speed(ifp); + new_speed = kernel_get_speed(ifp, &error); + + /* error may indicate vrf not available or + * interfaces not available. + * note that loopback & virtual interfaces can return 0 as speed + */ + if (error < 0) + return 1; + if (new_speed != ifp->speed) { zlog_info("%s: %s old speed: %u new speed: %u", __PRETTY_FUNCTION__, ifp->name, ifp->speed, @@ -261,8 +270,10 @@ struct interface *if_lookup_by_name_per_ns(struct zebra_ns *ns, for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) { ifp = (struct interface *)rn->info; - if (ifp && strcmp(ifp->name, ifname) == 0) + if (ifp && strcmp(ifp->name, ifname) == 0) { + route_unlock_node(rn); return (ifp); + } } return NULL; @@ -1556,7 +1567,7 @@ struct cmd_node interface_node = {INTERFACE_NODE, "%s(config-if)# ", 1}; #endif /* Show all interfaces to vty. */ DEFPY(show_interface, show_interface_cmd, - "show interface [vrf NAME$name] [brief$brief]", + "show interface [vrf NAME$vrf_name] [brief$brief]", SHOW_STR "Interface status and configuration\n" VRF_CMD_HELP_STR @@ -1568,8 +1579,8 @@ DEFPY(show_interface, show_interface_cmd, interface_update_stats(); - if (name) - VRF_GET_ID(vrf_id, name, false); + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name, false); /* All interface print. */ vrf = vrf_lookup_by_id(vrf_id); @@ -2034,13 +2045,13 @@ DEFUN (link_params_enable, /* This command could be issue at startup, when activate MPLS TE */ /* on a new interface or after a ON / OFF / ON toggle */ /* In all case, TE parameters are reset to their default factory */ - if (IS_ZEBRA_DEBUG_EVENT) + if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS) zlog_debug( "Link-params: enable TE link parameters on interface %s", ifp->name); if (!if_link_params_get(ifp)) { - if (IS_ZEBRA_DEBUG_EVENT) + if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS) zlog_debug( "Link-params: failed to init TE link parameters %s", ifp->name); @@ -2063,8 +2074,9 @@ DEFUN (no_link_params_enable, { VTY_DECLVAR_CONTEXT(interface, ifp); - zlog_debug("MPLS-TE: disable TE link parameters on interface %s", - ifp->name); + if (IS_ZEBRA_DEBUG_EVENT || IS_ZEBRA_DEBUG_MPLS) + zlog_debug("MPLS-TE: disable TE link parameters on interface %s", + ifp->name); if_link_params_free(ifp); diff --git a/zebra/redistribute.c b/zebra/redistribute.c index 4f72e2414a..227226b5f9 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -119,7 +119,7 @@ static void zebra_redistribute(struct zserv *client, int type, srcdest_rnode_prefixes(rn, &dst_p, &src_p); - if (IS_ZEBRA_DEBUG_EVENT) + if (IS_ZEBRA_DEBUG_RIB) zlog_debug( "%s: client %s %s(%u) checking: selected=%d, type=%d, distance=%d, metric=%d zebra_check_addr=%d", __func__, @@ -201,7 +201,7 @@ void redistribute_update(const struct prefix *p, const struct prefix *src_p, send_redistribute = 1; if (send_redistribute) { - if (IS_ZEBRA_DEBUG_EVENT) { + if (IS_ZEBRA_DEBUG_RIB) { zlog_debug( "%s: client %s %s(%u), type=%d, distance=%d, metric=%d", __func__, diff --git a/zebra/rt.h b/zebra/rt.h index 59b42fed18..f311a6b9d3 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -66,7 +66,7 @@ extern int kernel_interface_set_master(struct interface *master, extern int mpls_kernel_init(void); -extern uint32_t kernel_get_speed(struct interface *ifp); +extern uint32_t kernel_get_speed(struct interface *ifp, int *error); extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute); /* diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 91a3024038..43e44cad16 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1440,6 +1440,7 @@ static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc) static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, int llalen, ns_id_t ns_id) { + uint8_t protocol = RTPROT_ZEBRA; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -1460,6 +1461,8 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, req.ndm.ndm_ifindex = ifindex; req.ndm.ndm_type = RTN_UNICAST; + addattr_l(&req.n, sizeof(req), + NDA_PROTOCOL, &protocol, sizeof(protocol)); addattr_l(&req.n, sizeof(req), NDA_DST, &addr, 4); addattr_l(&req.n, sizeof(req), NDA_LLADDR, lla, llalen); @@ -1930,6 +1933,7 @@ int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd) { + uint8_t protocol = RTPROT_ZEBRA; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -1950,6 +1954,8 @@ static int netlink_vxlan_flood_update_ctx(const struct zebra_dplane_ctx *ctx, req.ndm.ndm_flags |= NTF_SELF; // Handle by "self", not "master" + addattr_l(&req.n, sizeof(req), + NDA_PROTOCOL, &protocol, sizeof(protocol)); addattr_l(&req.n, sizeof(req), NDA_LLADDR, &dst_mac, 6); req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx); @@ -2297,6 +2303,7 @@ int netlink_macfdb_read_specific_mac(struct zebra_ns *zns, static enum zebra_dplane_result netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx) { + uint8_t protocol = RTPROT_ZEBRA; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -2330,6 +2337,8 @@ netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx) else req.ndm.ndm_flags |= NTF_EXT_LEARNED; + addattr_l(&req.n, sizeof(req), + NDA_PROTOCOL, &protocol, sizeof(protocol)); addattr_l(&req.n, sizeof(req), NDA_LLADDR, dplane_ctx_mac_get_addr(ctx), 6); req.ndm.ndm_ifindex = dplane_ctx_get_ifindex(ctx); @@ -2748,6 +2757,7 @@ int netlink_neigh_change(struct nlmsghdr *h, ns_id_t ns_id) static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, int cmd) { + uint8_t protocol = RTPROT_ZEBRA; struct { struct nlmsghdr n; struct ndmsg ndm; @@ -2782,6 +2792,8 @@ static int netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx, req.ndm.ndm_type = RTN_UNICAST; req.ndm.ndm_flags = flags; + addattr_l(&req.n, sizeof(req), + NDA_PROTOCOL, &protocol, sizeof(protocol)); ipa_len = IS_IPADDR_V4(ip) ? IPV4_MAX_BYTELEN : IPV6_MAX_BYTELEN; addattr_l(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len); if (mac) diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index dc0f29bdbc..981ef7a889 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -396,7 +396,7 @@ extern int kernel_interface_set_master(struct interface *master, return 0; } -uint32_t kernel_get_speed(struct interface *ifp) +uint32_t kernel_get_speed(struct interface *ifp, int *error) { return ifp->speed; } diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c index 8cc5b52b34..711c4e0877 100644 --- a/zebra/rule_netlink.c +++ b/zebra/rule_netlink.c @@ -54,6 +54,7 @@ */ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule) { + uint8_t protocol = RTPROT_ZEBRA; int family; int bytelen; struct { @@ -78,6 +79,9 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule) req.frh.family = family; req.frh.action = FR_ACT_TO_TBL; + addattr_l(&req.n, sizeof(req), + FRA_PROTOCOL, &protocol, sizeof(protocol)); + /* rule's pref # */ addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->rule.priority); diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c index 4144c0afe0..5d88d4eeb4 100644 --- a/zebra/zebra_fpm.c +++ b/zebra/zebra_fpm.c @@ -711,7 +711,6 @@ static void zfpm_connection_down(const char *detail) * Start thread to clean up state after the connection goes down. */ assert(!zfpm_g->t_conn_down); - zfpm_debug("Starting conn_down thread"); zfpm_rnodes_iter_init(&zfpm_g->t_conn_down_state.iter); zfpm_g->t_conn_down = NULL; thread_add_timer_msec(zfpm_g->master, zfpm_conn_down_thread_cb, NULL, 0, @@ -806,8 +805,6 @@ static int zfpm_read_cb(struct thread *thread) goto done; } - zfpm_debug("Read out a full fpm message"); - /* * Just throw it away for now. */ @@ -1249,7 +1246,7 @@ static int zfpm_connect_cb(struct thread *t) sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { - zfpm_debug("Failed to create socket for connect(): %s", + zlog_err("Failed to create socket for connect(): %s", strerror(errno)); zfpm_g->stats.connect_no_sock++; return 0; diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5428b6eaef..98e66cd017 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -1556,7 +1556,9 @@ static bool rib_update_re_from_ctx(struct route_entry *re, changed_p = true; UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - break; + + /* Keep checking nexthops */ + continue; } if (CHECK_FLAG(ctx_nexthop->flags, NEXTHOP_FLAG_FIB)) { @@ -1992,6 +1994,9 @@ static void rib_process_dplane_notify(struct zebra_dplane_ctx *ctx) * not-installed; or not-installed to installed. */ if (start_count > 0 && end_count > 0) { + if (debug_p) + zlog_debug("%u:%s applied nexthop changes from dplane notification", + dplane_ctx_get_vrf(ctx), dest_str); /* Changed nexthops - update kernel/others */ dplane_route_notif_update(rn, re, diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index bcaf1b5204..5df5d94f4b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -337,7 +337,7 @@ static void addr2hostprefix(int af, const union g_addr *addr, break; default: memset(prefix, 0, sizeof(*prefix)); - zlog_debug("%s: unknown address family %d", __func__, af); + zlog_warn("%s: unknown address family %d", __func__, af); break; } } @@ -916,7 +916,8 @@ void zebra_print_rnh_table(vrf_id_t vrfid, afi_t afi, struct vty *vty, table = get_rnh_table(vrfid, afi, type); if (!table) { - zlog_debug("print_rnhs: rnh table not found"); + if (IS_ZEBRA_DEBUG_NHT) + zlog_debug("print_rnhs: rnh table not found"); return; } diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 72d0b6866d..4f1868311c 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -92,7 +92,7 @@ static int zebra_vrf_new(struct vrf *vrf) struct zebra_vrf *zvrf; if (IS_ZEBRA_DEBUG_EVENT) - zlog_info("VRF %s created, id %u", vrf->name, vrf->vrf_id); + zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id); zvrf = zebra_vrf_alloc(); vrf->info = zvrf; diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 515f19e8fe..5ce9d3f293 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -394,6 +394,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object *json_labels = NULL; time_t uptime; struct tm *tm; + struct vrf *vrf = NULL; rib_dest_t *dest = rib_dest_from_rnode(rn); struct nexthop_group *nhg; @@ -422,9 +423,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, json_object_int_add(json_route, "instance", re->instance); - if (re->vrf_id) + if (re->vrf_id) { json_object_int_add(json_route, "vrfId", re->vrf_id); + vrf = vrf_lookup_by_id(re->vrf_id); + json_object_string_add(json_route, "vrfName", + vrf->name); + } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) json_object_boolean_true_add(json_route, "selected"); @@ -565,9 +570,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if ((nexthop->vrf_id != re->vrf_id) && (nexthop->type != NEXTHOP_TYPE_BLACKHOLE)) { - struct vrf *vrf = - vrf_lookup_by_id(nexthop->vrf_id); - + vrf = vrf_lookup_by_id(nexthop->vrf_id); json_object_string_add(json_nexthop, "vrf", vrf->name); } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index c7f2976ace..2417b505ad 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -9153,6 +9153,11 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) if (zvni->advertise_svi_macip == advertise) return; + /* Store flag even though SVI is not present. + * Once SVI comes up triggers self MAC-IP route add. + */ + zvni->advertise_svi_macip = advertise; + ifp = zvni->vxlan_if; if (!ifp) return; @@ -9164,20 +9169,17 @@ void zebra_vxlan_advertise_svi_macip(ZAPI_HANDLER_ARGS) return; zl2_info = zif->l2info.vxl; - vlan_if = zvni_map_to_svi(zl2_info.access_vlan, zif->brslave_info.br_if); if (!vlan_if) return; if (advertise) { - zvni->advertise_svi_macip = advertise; /* Add primary SVI MAC-IP */ zvni_add_macip_for_intf(vlan_if, zvni); } else { - /* Del primary MAC-IP */ + /* Del primary SVI MAC-IP */ zvni_del_macip_for_intf(vlan_if, zvni); - zvni->advertise_svi_macip = advertise; } } |
