diff options
45 files changed, 2559 insertions, 294 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_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/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 c45a819362..88f1c4f627 100755 --- a/configure.ac +++ b/configure.ac @@ -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/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/isisd/isis_northbound.c b/isisd/isis_northbound.c index ccd4cfbd1c..1e21efa7ce 100644 --- a/isisd/isis_northbound.c +++ b/isisd/isis_northbound.c @@ -1559,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; 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", @@ -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/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/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/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/if_netlink.c b/zebra/if_netlink.c index 08fa77923d..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 */ diff --git a/zebra/interface.c b/zebra/interface.c index bb808e1852..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); 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_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/zebra_dplane.c b/zebra/zebra_dplane.c index 12f8a1ae3d..bf343e06e5 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -2511,6 +2511,18 @@ int dplane_show_provs_helper(struct vty *vty, bool detailed) } /* + * Helper for 'show run' etc. + */ +int dplane_config_write_helper(struct vty *vty) +{ + if (zdplane_info.dg_max_queued_updates != DPLANE_DEFAULT_MAX_QUEUED) + vty_out(vty, "zebra dplane limit %u\n", + zdplane_info.dg_max_queued_updates); + + return 0; +} + +/* * Provider registration */ int dplane_provider_register(const char *name, diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 30dfdafdf5..be945632c1 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -455,6 +455,7 @@ uint32_t dplane_get_in_queue_len(void); */ int dplane_show_helper(struct vty *vty, bool detailed); int dplane_show_provs_helper(struct vty *vty, bool detailed); +int dplane_config_write_helper(struct vty *vty); /* * Dataplane providers: modules that process or consume dataplane events. 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_vty.c b/zebra/zebra_vty.c index 15f0398ca4..5ce9d3f293 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -2658,6 +2658,10 @@ static int config_write_protocol(struct vty *vty) == MCAST_MIX_DISTANCE ? "lower-distance" : "longer-prefix"); + + /* Include dataplane info */ + dplane_config_write_helper(vty); + return 1; } 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; } } |
