diff options
87 files changed, 872 insertions, 513 deletions
diff --git a/Makefile.am b/Makefile.am index 65aed79152..474f8ab5b5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,7 @@ AUTOMAKE_OPTIONS = subdir-objects 1.12 ACLOCAL_AMFLAGS = -I m4 AM_CFLAGS = \ + $(UNWIND_CFLAGS) \ $(SAN_FLAGS) \ $(WERROR) \ # end @@ -18,6 +19,10 @@ AM_LDFLAGS = \ DEFS = @DEFS@ -DSYSCONFDIR=\"$(sysconfdir)/\" -DCONFDATE=$(CONFDATE) LIBCAP = @LIBCAP@ +AR_FLAGS = @AR_FLAGS@ +ARFLAGS = @ARFLAGS@ +RANLIB = @RANLIB@ + # these two targets are provided to easily grab autoconf/Makefile variables # you can use either: # eval `make VARFD=3 shvar-CFLAGS 3>&1 1>&2` diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 32fa02d99d..814366f320 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -861,15 +861,10 @@ static struct hash *bfd_vrf_hash; static struct hash *bfd_iface_hash; static unsigned int bfd_id_hash_do(void *p); -static int bfd_id_hash_cmp(const void *n1, const void *n2); static unsigned int bfd_shop_hash_do(void *p); -static int bfd_shop_hash_cmp(const void *n1, const void *n2); static unsigned int bfd_mhop_hash_do(void *p); -static int bfd_mhop_hash_cmp(const void *n1, const void *n2); static unsigned int bfd_vrf_hash_do(void *p); -static int bfd_vrf_hash_cmp(const void *n1, const void *n2); static unsigned int bfd_iface_hash_do(void *p); -static int bfd_iface_hash_cmp(const void *n1, const void *n2); static void _shop_key(struct bfd_session *bs, const struct bfd_shop_key *shop); static void _shop_key2(struct bfd_session *bs, const struct bfd_shop_key *shop); @@ -889,7 +884,7 @@ static unsigned int bfd_id_hash_do(void *p) return jhash_1word(bs->discrs.my_discr, 0); } -static int bfd_id_hash_cmp(const void *n1, const void *n2) +static bool bfd_id_hash_cmp(const void *n1, const void *n2) { const struct bfd_session *bs1 = n1, *bs2 = n2; @@ -904,7 +899,7 @@ static unsigned int bfd_shop_hash_do(void *p) return jhash(&bs->shop, sizeof(bs->shop), 0); } -static int bfd_shop_hash_cmp(const void *n1, const void *n2) +static bool bfd_shop_hash_cmp(const void *n1, const void *n2) { const struct bfd_session *bs1 = n1, *bs2 = n2; @@ -919,7 +914,7 @@ static unsigned int bfd_mhop_hash_do(void *p) return jhash(&bs->mhop, sizeof(bs->mhop), 0); } -static int bfd_mhop_hash_cmp(const void *n1, const void *n2) +static bool bfd_mhop_hash_cmp(const void *n1, const void *n2) { const struct bfd_session *bs1 = n1, *bs2 = n2; @@ -934,7 +929,7 @@ static unsigned int bfd_vrf_hash_do(void *p) return jhash_1word(vrf->vrf_id, 0); } -static int bfd_vrf_hash_cmp(const void *n1, const void *n2) +static bool bfd_vrf_hash_cmp(const void *n1, const void *n2) { const struct bfd_vrf *v1 = n1, *v2 = n2; @@ -949,7 +944,7 @@ static unsigned int bfd_iface_hash_do(void *p) return string_hash_make(iface->ifname); } -static int bfd_iface_hash_cmp(const void *n1, const void *n2) +static bool bfd_iface_hash_cmp(const void *n1, const void *n2) { const struct bfd_iface *i1 = n1, *i2 = n2; diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c index 51dd9cb26d..8f8fff6b18 100644 --- a/bfdd/bfdd_vty.c +++ b/bfdd/bfdd_vty.c @@ -90,7 +90,7 @@ DEFUN_NOSH(bfd_enter, bfd_enter_cmd, "bfd", "Configure BFD peers\n") DEFUN_NOSH( bfd_peer_enter, bfd_peer_enter_cmd, - "peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]", + "peer <A.B.C.D|X:X::X:X> [{[multihop] local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]", PEER_STR PEER_IPV4_STR PEER_IPV6_STR MHOP_STR LOCAL_STR LOCAL_IPV4_STR LOCAL_IPV6_STR diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index be47cbb6d8..5b2cb57921 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -71,7 +71,7 @@ unsigned int baa_hash_key(void *p) return attrhash_key_make(baa->attr); } -int baa_hash_cmp(const void *p1, const void *p2) +bool baa_hash_cmp(const void *p1, const void *p2) { const struct bgp_advertise_attr *baa1 = p1; const struct bgp_advertise_attr *baa2 = p2; diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index 6ff476e7b8..1912aec1bf 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -177,7 +177,7 @@ extern void bgp_adj_in_remove(struct bgp_node *, struct bgp_adj_in *); extern void bgp_sync_init(struct peer *); extern void bgp_sync_delete(struct peer *); extern unsigned int baa_hash_key(void *p); -extern int baa_hash_cmp(const void *p1, const void *p2); +extern bool baa_hash_cmp(const void *p1, const void *p2); extern void bgp_advertise_add(struct bgp_advertise_attr *baa, struct bgp_advertise *adv); extern struct bgp_advertise *bgp_advertise_new(void); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 0924223ddc..4f756519ca 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -1726,23 +1726,23 @@ struct aspath *aspath_reconcile_as4(struct aspath *aspath, /* Compare leftmost AS value for MED check. If as1's leftmost AS and as2's leftmost AS is same return 1. (confederation as-path only). */ -int aspath_cmp_left_confed(const struct aspath *aspath1, - const struct aspath *aspath2) +bool aspath_cmp_left_confed(const struct aspath *aspath1, + const struct aspath *aspath2) { if (!(aspath1 && aspath2)) - return 0; + return false; if (!(aspath1->segments && aspath2->segments)) - return 0; + return false; if ((aspath1->segments->type != AS_CONFED_SEQUENCE) || (aspath2->segments->type != AS_CONFED_SEQUENCE)) - return 0; + return false; if (aspath1->segments->as[0] == aspath2->segments->as[0]) - return 1; + return true; - return 0; + return false; } /* Delete all AS_CONFED_SEQUENCE/SET segments from aspath. @@ -2008,7 +2008,7 @@ unsigned int aspath_key_make(void *p) } /* If two aspath have same value then return 1 else return 0 */ -int aspath_cmp(const void *arg1, const void *arg2) +bool aspath_cmp(const void *arg1, const void *arg2) { const struct assegment *seg1 = ((const struct aspath *)arg1)->segments; const struct assegment *seg2 = ((const struct aspath *)arg2)->segments; @@ -2016,18 +2016,18 @@ int aspath_cmp(const void *arg1, const void *arg2) while (seg1 || seg2) { int i; if ((!seg1 && seg2) || (seg1 && !seg2)) - return 0; + return false; if (seg1->type != seg2->type) - return 0; + return false; if (seg1->length != seg2->length) - return 0; + return false; for (i = 0; i < seg1->length; i++) if (seg1->as[i] != seg2->as[i]) - return 0; + return false; seg1 = seg1->next; seg2 = seg2->next; } - return 1; + return true; } /* AS path hash initialize. */ diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index 1acc2f67a6..9c9c687a6b 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -85,9 +85,10 @@ extern struct aspath *aspath_filter_exclude(struct aspath *, struct aspath *); extern struct aspath *aspath_add_seq_n(struct aspath *, as_t, unsigned); extern struct aspath *aspath_add_seq(struct aspath *, as_t); extern struct aspath *aspath_add_confed_seq(struct aspath *, as_t); -extern int aspath_cmp(const void *, const void *); +extern bool aspath_cmp(const void *as1, const void *as2); extern int aspath_cmp_left(const struct aspath *, const struct aspath *); -extern int aspath_cmp_left_confed(const struct aspath *, const struct aspath *); +extern bool aspath_cmp_left_confed(const struct aspath *as1, + const struct aspath *as2xs); extern struct aspath *aspath_delete_confed_seq(struct aspath *); extern struct aspath *aspath_empty(void); extern struct aspath *aspath_empty_get(void); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index c7d7c56a12..e183073eca 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -146,7 +146,7 @@ static unsigned int cluster_hash_key_make(void *p) return jhash(cluster->list, cluster->length, 0); } -static int cluster_hash_cmp(const void *p1, const void *p2) +static bool cluster_hash_cmp(const void *p1, const void *p2) { const struct cluster_list *cluster1 = p1; const struct cluster_list *cluster2 = p2; @@ -355,7 +355,7 @@ static unsigned int encap_hash_key_make(void *p) return jhash(encap->value, encap->length, 0); } -static int encap_hash_cmp(const void *p1, const void *p2) +static bool encap_hash_cmp(const void *p1, const void *p2) { return encap_same((const struct bgp_attr_encap_subtlv *)p1, (const struct bgp_attr_encap_subtlv *)p2); @@ -441,7 +441,7 @@ static unsigned int transit_hash_key_make(void *p) return jhash(transit->val, transit->length, 0); } -static int transit_hash_cmp(const void *p1, const void *p2) +static bool transit_hash_cmp(const void *p1, const void *p2) { const struct transit *transit1 = p1; const struct transit *transit2 = p2; @@ -527,7 +527,7 @@ unsigned int attrhash_key_make(void *p) return key; } -int attrhash_cmp(const void *p1, const void *p2) +bool attrhash_cmp(const void *p1, const void *p2) { const struct attr *attr1 = p1; const struct attr *attr2 = p2; @@ -565,10 +565,10 @@ int attrhash_cmp(const void *p1, const void *p2) && overlay_index_same(attr1, attr2) && attr1->nh_ifindex == attr2->nh_ifindex && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex) - return 1; + return true; } - return 0; + return false; } static void attrhash_init(void) @@ -723,8 +723,10 @@ struct attr *bgp_attr_default_set(struct attr *attr, uint8_t origin) /* Create the attributes for an aggregate */ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, struct aspath *aspath, - struct community *community, int as_set, - uint8_t atomic_aggregate) + struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, + int as_set, uint8_t atomic_aggregate) { struct attr attr; struct attr *new; @@ -760,6 +762,16 @@ struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } + if (ecommunity) { + attr.ecommunity = ecommunity; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + } + + if (lcommunity) { + attr.lcommunity = lcommunity; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES); + } + if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { bgp_attr_add_gshut_community(&attr); } diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 883b129136..47a4182fee 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -272,10 +272,13 @@ extern void bgp_attr_unintern_sub(struct attr *); extern void bgp_attr_unintern(struct attr **); extern void bgp_attr_flush(struct attr *); extern struct attr *bgp_attr_default_set(struct attr *attr, uint8_t); -extern struct attr *bgp_attr_aggregate_intern(struct bgp *, uint8_t, - struct aspath *, - struct community *, int as_set, - uint8_t); +extern struct attr *bgp_attr_aggregate_intern(struct bgp *bgp, uint8_t origin, + struct aspath *aspath, + struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, + int as_set, + uint8_t atomic_aggregate); extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, struct stream *, struct attr *, struct bpacket_attr_vec_arr *vecarr, @@ -284,7 +287,7 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, mpls_label_t *, uint32_t, int, uint32_t); extern void bgp_dump_routes_attr(struct stream *, struct attr *, struct prefix *); -extern int attrhash_cmp(const void *, const void *); +extern bool attrhash_cmp(const void *arg1, const void *arg2); extern unsigned int attrhash_key_make(void *); extern void attr_show_all(struct vty *); extern unsigned long int attr_count(void); diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index e40674d635..9e5eb273a0 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -614,17 +614,17 @@ int community_match(const struct community *com1, const struct community *com2) /* If two aspath have same value then return 1 else return 0. This function is used by hash package. */ -int community_cmp(const struct community *com1, const struct community *com2) +bool community_cmp(const struct community *com1, const struct community *com2) { if (com1 == NULL && com2 == NULL) - return 1; + return true; if (com1 == NULL || com2 == NULL) - return 0; + return false; if (com1->size == com2->size) if (memcmp(com1->val, com2->val, com1->size * 4) == 0) - return 1; - return 0; + return true; + return false; } /* Add com2 to the end of com1. */ @@ -902,7 +902,7 @@ void community_init(void) { comhash = hash_create((unsigned int (*)(void *))community_hash_make, - (int (*)(const void *, const void *))community_cmp, + (bool (*)(const void *, const void *))community_cmp, "BGP Community Hash"); } diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index 61af9f038c..afb9876f29 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -77,7 +77,8 @@ extern char *community_str(struct community *, bool make_json); extern unsigned int community_hash_make(struct community *); extern struct community *community_str2com(const char *); extern int community_match(const struct community *, const struct community *); -extern int community_cmp(const struct community *, const struct community *); +extern bool community_cmp(const struct community *c1, + const struct community *c2); extern struct community *community_merge(struct community *, struct community *); extern struct community *community_delete(struct community *, diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c index cff5caf52f..86cee39a62 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -448,12 +448,15 @@ static void bgp_damp_config_clean(struct bgp_damp_config *damp) { /* Free decay array */ XFREE(MTYPE_BGP_DAMP_ARRAY, damp->decay_array); + damp->decay_array_size = 0; /* Free reuse index array */ XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_index); + damp->reuse_index_size = 0; /* Free reuse list array. */ XFREE(MTYPE_BGP_DAMP_ARRAY, damp->reuse_list); + damp->reuse_list_size = 0; } /* Clean all the bgp_damp_info stored in reuse_list. */ diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 2e5b219ef9..8029164184 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -253,16 +253,16 @@ unsigned int ecommunity_hash_make(void *arg) } /* Compare two Extended Communities Attribute structure. */ -int ecommunity_cmp(const void *arg1, const void *arg2) +bool ecommunity_cmp(const void *arg1, const void *arg2) { const struct ecommunity *ecom1 = arg1; const struct ecommunity *ecom2 = arg2; if (ecom1 == NULL && ecom2 == NULL) - return 1; + return true; if (ecom1 == NULL || ecom2 == NULL) - return 0; + return false; return (ecom1->size == ecom2->size && memcmp(ecom1->val, ecom2->val, ecom1->size * ECOMMUNITY_SIZE) diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index c71f371a97..d43403ed8d 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -154,7 +154,7 @@ extern struct ecommunity *ecommunity_merge(struct ecommunity *, struct ecommunity *); extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *); extern struct ecommunity *ecommunity_intern(struct ecommunity *); -extern int ecommunity_cmp(const void *, const void *); +extern bool ecommunity_cmp(const void *arg1, const void *arg2); extern void ecommunity_unintern(struct ecommunity **); extern unsigned int ecommunity_hash_make(void *); extern struct ecommunity *ecommunity_str2com(const char *, int, int); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index d6ed84ff56..b67d93d4f5 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -92,16 +92,16 @@ static unsigned int esi_hash_keymake(void *p) /* * Compare two ESIs. */ -static int esi_cmp(const void *p1, const void *p2) +static bool esi_cmp(const void *p1, const void *p2) { const struct evpnes *pes1 = p1; const struct evpnes *pes2 = p2; if (pes1 == NULL && pes2 == NULL) - return 1; + return true; if (pes1 == NULL || pes2 == NULL) - return 0; + return false; return (memcmp(pes1->esi.val, pes2->esi.val, ESI_BYTES) == 0); } @@ -118,15 +118,15 @@ static unsigned int vni_hash_key_make(void *p) /* * Comparison function for vni hash */ -static int vni_hash_cmp(const void *p1, const void *p2) +static bool vni_hash_cmp(const void *p1, const void *p2) { const struct bgpevpn *vpn1 = p1; const struct bgpevpn *vpn2 = p2; if (!vpn1 && !vpn2) - return 1; + return true; if (!vpn1 || !vpn2) - return 0; + return false; return (vpn1->vni == vpn2->vni); } @@ -152,16 +152,16 @@ static unsigned int vrf_import_rt_hash_key_make(void *p) /* * Comparison function for vrf import rt hash */ -static int vrf_import_rt_hash_cmp(const void *p1, const void *p2) +static bool vrf_import_rt_hash_cmp(const void *p1, const void *p2) { const struct vrf_irt_node *irt1 = p1; const struct vrf_irt_node *irt2 = p2; if (irt1 == NULL && irt2 == NULL) - return 1; + return true; if (irt1 == NULL || irt2 == NULL) - return 0; + return false; return (memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0); } @@ -269,16 +269,16 @@ static unsigned int import_rt_hash_key_make(void *p) /* * Comparison function for import rt hash */ -static int import_rt_hash_cmp(const void *p1, const void *p2) +static bool import_rt_hash_cmp(const void *p1, const void *p2) { const struct irt_node *irt1 = p1; const struct irt_node *irt2 = p2; if (irt1 == NULL && irt2 == NULL) - return 1; + return true; if (irt1 == NULL || irt2 == NULL) - return 0; + return false; return (memcmp(irt1->rt.val, irt2->rt.val, ECOMMUNITY_SIZE) == 0); } diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index 91fa8fa373..50aad70ddc 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -123,10 +123,11 @@ static void peer_process(struct hash_backet *hb, void *arg) *next_update = diff; } -static int peer_hash_cmp(const void *f, const void *s) +static bool peer_hash_cmp(const void *f, const void *s) { const struct pkat *p1 = f; const struct pkat *p2 = s; + return p1->peer == p2->peer; } diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 3e160bc56e..cfc9af7777 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -313,11 +313,17 @@ unsigned int lcommunity_hash_make(void *arg) } /* Compare two Large Communities Attribute structure. */ -int lcommunity_cmp(const void *arg1, const void *arg2) +bool lcommunity_cmp(const void *arg1, const void *arg2) { const struct lcommunity *lcom1 = arg1; const struct lcommunity *lcom2 = arg2; + if (lcom1 == NULL && lcom2 == NULL) + return 1; + + if (lcom1 == NULL || lcom2 == NULL) + return 0; + return (lcom1->size == lcom2->size && memcmp(lcom1->val, lcom2->val, lcom_length(lcom1)) == 0); } diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index c88a016396..23c777d9fd 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -60,7 +60,7 @@ extern struct lcommunity *lcommunity_merge(struct lcommunity *, struct lcommunity *); extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *); extern struct lcommunity *lcommunity_intern(struct lcommunity *); -extern int lcommunity_cmp(const void *, const void *); +extern bool lcommunity_cmp(const void *arg1, const void *arg2); extern void lcommunity_unintern(struct lcommunity **); extern unsigned int lcommunity_hash_make(void *); extern struct hash *lcommunity_hash(void); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 45c596254f..5ed6fd6ebe 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -84,11 +84,18 @@ static void bgp_nexthop_cache_reset(struct bgp_table *table) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { bnc = bgp_nexthop_get_node_info(rn); - if (bnc != NULL) { - bnc_free(bnc); - bgp_nexthop_set_node_info(rn, NULL); - bgp_unlock_node(rn); + if (!bnc) + continue; + + while (!LIST_EMPTY(&(bnc->paths))) { + struct bgp_path_info *path = LIST_FIRST(&(bnc->paths)); + + path_nh_map(path, bnc, false); } + + bnc_free(bnc); + bgp_nexthop_set_node_info(rn, NULL); + bgp_unlock_node(rn); } } @@ -116,7 +123,7 @@ static unsigned int bgp_tip_hash_key_make(void *p) return jhash_1word(addr->addr.s_addr, 0); } -static int bgp_tip_hash_cmp(const void *p1, const void *p2) +static bool bgp_tip_hash_cmp(const void *p1, const void *p2) { const struct tip_addr *addr1 = p1; const struct tip_addr *addr2 = p2; @@ -239,7 +246,7 @@ static unsigned int bgp_address_hash_key_make(void *p) return jhash_1word(addr->addr.s_addr, 0); } -static int bgp_address_hash_cmp(const void *p1, const void *p2) +static bool bgp_address_hash_cmp(const void *p1, const void *p2) { const struct bgp_addr *addr1 = p1; const struct bgp_addr *addr2 = p2; diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 5203e6eefd..e764860bcc 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -51,8 +51,6 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, int is_bgp_static_route); static void evaluate_paths(struct bgp_nexthop_cache *bnc); static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p); -static void path_nh_map(struct bgp_path_info *path, - struct bgp_nexthop_cache *bnc, int keep); static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc) { @@ -111,7 +109,7 @@ void bgp_unlink_nexthop(struct bgp_path_info *path) if (!bnc) return; - path_nh_map(path, NULL, 0); + path_nh_map(path, NULL, false); bgp_unlink_nexthop_check(bnc); } @@ -253,7 +251,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, */ bgp_unlink_nexthop(pi); - path_nh_map(pi, bnc, 1); /* updates NHT pi list reference */ + /* updates NHT pi list reference */ + path_nh_map(pi, bnc, true); if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric; @@ -789,8 +788,8 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) * make - if set, make the association. if unset, just break the existing * association. */ -static void path_nh_map(struct bgp_path_info *path, - struct bgp_nexthop_cache *bnc, int make) +void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc, + bool make) { if (path->nexthop) { LIST_REMOVE(path, nh_thread); diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index 7b29fa818f..0cc045a065 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -75,4 +75,11 @@ extern void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer); */ extern void bgp_cleanup_nexthops(struct bgp *bgp); +/* + * Add or remove the tracking of the bgp_path_info that + * uses this nexthop + */ +extern void path_nh_map(struct bgp_path_info *path, + struct bgp_nexthop_cache *bnc, bool make); + #endif /* _BGP_NHT_H */ diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 263a3ebf4d..edd8317c31 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -847,7 +847,7 @@ uint32_t bgp_pbr_match_hash_key(void *arg) return jhash_1word(pbm->type, key); } -int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2) +bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2) { const struct bgp_pbr_match *r1, *r2; @@ -855,35 +855,35 @@ int bgp_pbr_match_hash_equal(const void *arg1, const void *arg2) r2 = (const struct bgp_pbr_match *)arg2; if (r1->vrf_id != r2->vrf_id) - return 0; + return false; if (r1->type != r2->type) - return 0; + return false; if (r1->flags != r2->flags) - return 0; + return false; if (r1->action != r2->action) - return 0; + return false; if (r1->pkt_len_min != r2->pkt_len_min) - return 0; + return false; if (r1->pkt_len_max != r2->pkt_len_max) - return 0; + return false; if (r1->tcp_flags != r2->tcp_flags) - return 0; + return false; if (r1->tcp_mask_flags != r2->tcp_mask_flags) - return 0; + return false; if (r1->dscp_value != r2->dscp_value) - return 0; + return false; if (r1->fragment != r2->fragment) - return 0; - return 1; + return false; + return true; } uint32_t bgp_pbr_match_entry_hash_key(void *arg) @@ -903,45 +903,41 @@ uint32_t bgp_pbr_match_entry_hash_key(void *arg) return key; } -int bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2) +bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2) { const struct bgp_pbr_match_entry *r1, *r2; r1 = (const struct bgp_pbr_match_entry *)arg1; r2 = (const struct bgp_pbr_match_entry *)arg2; - /* on updates, comparing - * backpointer is not necessary - */ - - /* unique value is self calculated - */ - - /* rate is ignored for now + /* + * on updates, comparing backpointer is not necessary + * unique value is self calculated + * rate is ignored for now */ if (!prefix_same(&r1->src, &r2->src)) - return 0; + return false; if (!prefix_same(&r1->dst, &r2->dst)) - return 0; + return false; if (r1->src_port_min != r2->src_port_min) - return 0; + return false; if (r1->dst_port_min != r2->dst_port_min) - return 0; + return false; if (r1->src_port_max != r2->src_port_max) - return 0; + return false; if (r1->dst_port_max != r2->dst_port_max) - return 0; + return false; if (r1->proto != r2->proto) - return 0; + return false; - return 1; + return true; } uint32_t bgp_pbr_action_hash_key(void *arg) @@ -955,7 +951,7 @@ uint32_t bgp_pbr_action_hash_key(void *arg) return key; } -int bgp_pbr_action_hash_equal(const void *arg1, const void *arg2) +bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2) { const struct bgp_pbr_action *r1, *r2; @@ -967,11 +963,12 @@ int bgp_pbr_action_hash_equal(const void *arg1, const void *arg2) * rate is ignored */ if (r1->vrf_id != r2->vrf_id) - return 0; + return false; if (memcmp(&r1->nh, &r2->nh, sizeof(struct nexthop))) - return 0; - return 1; + return false; + + return true; } struct bgp_pbr_action *bgp_pbr_action_rule_lookup(vrf_id_t vrf_id, diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index d15cb39c32..84095f9ab9 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -267,13 +267,13 @@ extern void bgp_pbr_cleanup(struct bgp *bgp); extern void bgp_pbr_init(struct bgp *bgp); extern uint32_t bgp_pbr_action_hash_key(void *arg); -extern int bgp_pbr_action_hash_equal(const void *arg1, +extern bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2); extern uint32_t bgp_pbr_match_entry_hash_key(void *arg); -extern int bgp_pbr_match_entry_hash_equal(const void *arg1, +extern bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2); extern uint32_t bgp_pbr_match_hash_key(void *arg); -extern int bgp_pbr_match_hash_equal(const void *arg1, +extern bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2); void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index c15ce7d9aa..bb6b8aab3c 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -5482,7 +5482,9 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate) static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, struct aspath *aspath, - struct community *comm) + struct community *comm, + struct ecommunity *ecomm, + struct lcommunity *lcomm) { static struct aspath *ae = NULL; @@ -5501,6 +5503,12 @@ static int bgp_aggregate_info_same(struct bgp_path_info *pi, uint8_t origin, if (!community_cmp(pi->attr->community, comm)) return 0; + if (!ecommunity_cmp(pi->attr->ecommunity, ecomm)) + return 0; + + if (!lcommunity_cmp(pi->attr->lcommunity, lcomm)) + return 0; + if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID)) return 0; @@ -5511,6 +5519,8 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, uint8_t origin, struct aspath *aspath, struct community *community, + struct ecommunity *ecommunity, + struct lcommunity *lcommunity, uint8_t atomic_aggregate, struct bgp_aggregate *aggregate) { @@ -5532,14 +5542,18 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, * If the aggregate information has not changed * no need to re-install it again. */ - if (bgp_aggregate_info_same(rn->info, origin, aspath, - community)) { + if (bgp_aggregate_info_same(rn->info, origin, aspath, community, + ecommunity, lcommunity)) { bgp_unlock_node(rn); if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); return; } @@ -5550,12 +5564,14 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, if (pi) bgp_path_info_delete(rn, pi); - new = info_make( - ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, bgp->peer_self, - bgp_attr_aggregate_intern(bgp, origin, aspath, - community, aggregate->as_set, - atomic_aggregate), - rn); + new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_AGGREGATE, 0, + bgp->peer_self, + bgp_attr_aggregate_intern(bgp, origin, aspath, + community, ecommunity, + lcommunity, + aggregate->as_set, + atomic_aggregate), + rn); SET_FLAG(new->flags, BGP_PATH_VALID); bgp_path_info_add(rn, new); @@ -5591,6 +5607,10 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, struct aspath *asmerge = NULL; struct community *community = NULL; struct community *commerge = NULL; + struct ecommunity *ecommunity = NULL; + struct ecommunity *ecommerge = NULL; + struct lcommunity *lcommunity = NULL; + struct lcommunity *lcommerge = NULL; struct bgp_path_info *pi; unsigned long match = 0; uint8_t atomic_aggregate = 0; @@ -5670,16 +5690,43 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, } else aspath = aspath_dup(pi->attr->aspath); - if (!pi->attr->community) - continue; + if (pi->attr->community) { + if (community) { + commerge = community_merge( + community, pi->attr->community); + community = + community_uniq_sort(commerge); + community_free(commerge); + } else + community = community_dup( + pi->attr->community); + } - if (community) { - commerge = community_merge(community, - pi->attr->community); - community = community_uniq_sort(commerge); - community_free(commerge); - } else - community = community_dup(pi->attr->community); + if (pi->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pi->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pi->attr->ecommunity); + } + + if (pi->attr->lcommunity) { + if (lcommunity) { + lcommerge = lcommunity_merge( + lcommunity, + pi->attr->lcommunity); + lcommunity = + lcommunity_uniq_sort(lcommerge); + lcommunity_free(&lcommerge); + } else + lcommunity = lcommunity_dup( + pi->attr->lcommunity); + } } if (match) bgp_process(bgp, rn, afi, safi); @@ -5716,17 +5763,48 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, community = community_dup( pinew->attr->community); } + + if (pinew->attr->ecommunity) { + if (ecommunity) { + ecommerge = ecommunity_merge( + ecommunity, + pinew->attr->ecommunity); + ecommunity = + ecommunity_uniq_sort(ecommerge); + ecommunity_free(&ecommerge); + } else + ecommunity = ecommunity_dup( + pinew->attr->ecommunity); + } + + if (pinew->attr->lcommunity) { + if (lcommunity) { + lcommerge = lcommunity_merge( + lcommunity, + pinew->attr->lcommunity); + lcommunity = + lcommunity_uniq_sort(lcommerge); + lcommunity_free(&lcommerge); + } else + lcommunity = lcommunity_dup( + pinew->attr->lcommunity); + } } } bgp_aggregate_install(bgp, afi, safi, p, origin, aspath, community, - atomic_aggregate, aggregate); + ecommunity, lcommunity, atomic_aggregate, + aggregate); if (aggregate->count == 0) { if (aspath) aspath_free(aspath); if (community) community_free(community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); } } @@ -5871,7 +5949,8 @@ static int bgp_aggregate_unset(struct vty *vty, const char *prefix_str, aggregate = bgp_aggregate_get_node_info(rn); bgp_aggregate_delete(bgp, &p, afi, safi, aggregate); - bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, 0, aggregate); + bgp_aggregate_install(bgp, afi, safi, &p, 0, NULL, NULL, + NULL, NULL, 0, aggregate); /* Unlock aggregate address configuration. */ bgp_aggregate_set_node_info(rn, NULL); diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index d468d48d86..ca0291d0a1 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1403,45 +1403,45 @@ static route_map_result_t route_set_ip_nexthop(void *rule, struct bgp_path_info *path; struct peer *peer; - if (type == RMAP_BGP) { - path = object; - peer = path->peer; + if (type != RMAP_BGP) + return RMAP_OKAY; - if (rins->unchanged) { - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_UNCHANGED); - } else if (rins->peer_address) { - if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) - || CHECK_FLAG(peer->rmap_type, - PEER_RMAP_TYPE_IMPORT)) - && peer->su_remote - && sockunion_family(peer->su_remote) == AF_INET) { - path->attr->nexthop.s_addr = - sockunion2ip(peer->su_remote); - path->attr->flag |= - ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); - } else if (CHECK_FLAG(peer->rmap_type, - PEER_RMAP_TYPE_OUT)) { - /* The next hop value will be set as part of - * packet rewrite. - * Set the flags here to indicate that rewrite - * needs to be done. - * Also, clear the value. - */ - SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS); - path->attr->nexthop.s_addr = 0; - } - } else { - /* Set next hop value. */ + if (prefix->family == AF_INET6) + return RMAP_OKAY; + + path = object; + peer = path->peer; + + if (rins->unchanged) { + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_NEXTHOP_UNCHANGED); + } else if (rins->peer_address) { + if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) + || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) + && peer->su_remote + && sockunion_family(peer->su_remote) == AF_INET) { + path->attr->nexthop.s_addr = + sockunion2ip(peer->su_remote); path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); - path->attr->nexthop = *rins->address; + } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) { + /* The next hop value will be set as part of + * packet rewrite. Set the flags here to indicate + * that rewrite needs to be done. + * Also, clear the value. + */ SET_FLAG(path->attr->rmap_change_flags, - BATTR_RMAP_IPV4_NHOP_CHANGED); - /* case for MP-BGP : MPLS VPN */ - path->attr->mp_nexthop_global_in = *rins->address; - path->attr->mp_nexthop_len = sizeof(*rins->address); + BATTR_RMAP_NEXTHOP_PEER_ADDRESS); + path->attr->nexthop.s_addr = 0; } + } else { + /* Set next hop value. */ + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + path->attr->nexthop = *rins->address; + SET_FLAG(path->attr->rmap_change_flags, + BATTR_RMAP_IPV4_NHOP_CHANGED); + /* case for MP-BGP : MPLS VPN */ + path->attr->mp_nexthop_global_in = *rins->address; + path->attr->mp_nexthop_len = sizeof(*rins->address); } return RMAP_OKAY; diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 6ebfc4af02..393586dbec 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -393,7 +393,7 @@ static unsigned int updgrp_hash_key_make(void *p) return key; } -static int updgrp_hash_cmp(const void *p1, const void *p2) +static bool updgrp_hash_cmp(const void *p1, const void *p2) { const struct update_group *grp1; const struct update_group *grp2; @@ -407,7 +407,7 @@ static int updgrp_hash_cmp(const void *p1, const void *p2) safi_t safi; if (!p1 || !p2) - return 0; + return false; grp1 = p1; grp2 = p2; @@ -422,68 +422,68 @@ static int updgrp_hash_cmp(const void *p1, const void *p2) /* put EBGP and IBGP peers in different update groups */ if (pe1->sort != pe2->sort) - return 0; + return false; /* check peer flags */ if ((pe1->flags & PEER_UPDGRP_FLAGS) != (pe2->flags & PEER_UPDGRP_FLAGS)) - return 0; + return false; /* If there is 'local-as' configured, it should match. */ if (pe1->change_local_as != pe2->change_local_as) - return 0; + return false; /* flags like route reflector client */ if ((flags1 & PEER_UPDGRP_AF_FLAGS) != (flags2 & PEER_UPDGRP_AF_FLAGS)) - return 0; + return false; if ((pe1->cap & PEER_UPDGRP_CAP_FLAGS) != (pe2->cap & PEER_UPDGRP_CAP_FLAGS)) - return 0; + return false; if ((pe1->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS) != (pe2->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS)) - return 0; + return false; if (pe1->v_routeadv != pe2->v_routeadv) - return 0; + return false; if (pe1->group != pe2->group) - return 0; + return false; /* route-map names should be the same */ if ((fl1->map[RMAP_OUT].name && !fl2->map[RMAP_OUT].name) || (!fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name) || (fl1->map[RMAP_OUT].name && fl2->map[RMAP_OUT].name && strcmp(fl1->map[RMAP_OUT].name, fl2->map[RMAP_OUT].name))) - return 0; + return false; if ((fl1->dlist[FILTER_OUT].name && !fl2->dlist[FILTER_OUT].name) || (!fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name) || (fl1->dlist[FILTER_OUT].name && fl2->dlist[FILTER_OUT].name && strcmp(fl1->dlist[FILTER_OUT].name, fl2->dlist[FILTER_OUT].name))) - return 0; + return false; if ((fl1->plist[FILTER_OUT].name && !fl2->plist[FILTER_OUT].name) || (!fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name) || (fl1->plist[FILTER_OUT].name && fl2->plist[FILTER_OUT].name && strcmp(fl1->plist[FILTER_OUT].name, fl2->plist[FILTER_OUT].name))) - return 0; + return false; if ((fl1->aslist[FILTER_OUT].name && !fl2->aslist[FILTER_OUT].name) || (!fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name) || (fl1->aslist[FILTER_OUT].name && fl2->aslist[FILTER_OUT].name && strcmp(fl1->aslist[FILTER_OUT].name, fl2->aslist[FILTER_OUT].name))) - return 0; + return false; if ((fl1->usmap.name && !fl2->usmap.name) || (!fl1->usmap.name && fl2->usmap.name) || (fl1->usmap.name && fl2->usmap.name && strcmp(fl1->usmap.name, fl2->usmap.name))) - return 0; + return false; if ((pe1->default_rmap[afi][safi].name && !pe2->default_rmap[afi][safi].name) @@ -493,19 +493,19 @@ static int updgrp_hash_cmp(const void *p1, const void *p2) && pe2->default_rmap[afi][safi].name && strcmp(pe1->default_rmap[afi][safi].name, pe2->default_rmap[afi][safi].name))) - return 0; + return false; if ((afi == AFI_IP6) && (pe1->shared_network != pe2->shared_network)) - return 0; + return false; if ((CHECK_FLAG(pe1->flags, PEER_FLAG_LONESOUL) || CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_RCV) || CHECK_FLAG(pe1->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_OLD_RCV)) && !sockunion_same(&pe1->su, &pe2->su)) - return 0; + return false; - return 1; + return true; } static void peer_lonesoul_or_not(struct peer *peer, int set) diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 88025337b2..01d33a869d 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2740,7 +2740,8 @@ static int peer_remote_as_vty(struct vty *vty, const char *peer_str, ret = peer_group_remote_as(bgp, peer_str, &as, as_type); if (ret < 0) { vty_out(vty, - "%% Create the peer-group or interface first\n"); + "%% Create the peer-group or interface first or specify \"interface\" keyword\n"); + vty_out(vty, "%% if using an unnumbered interface neighbor\n"); return CMD_WARNING_CONFIG_FAILED; } return CMD_SUCCESS; @@ -11375,6 +11376,23 @@ DEFUN (show_bgp_instance_all_ipv6_updgrps, return CMD_SUCCESS; } +DEFUN (show_bgp_l2vpn_evpn_updgrps, + show_bgp_l2vpn_evpn_updgrps_cmd, + "show [ip] bgp l2vpn evpn update-groups", + SHOW_STR + IP_STR + BGP_STR + "l2vpn address family\n" + "evpn sub-address family\n" + "Detailed info about dynamic update groups\n") +{ + char *vrf = NULL; + uint64_t subgrp_id = 0; + + bgp_show_update_groups(vty, vrf, AFI_L2VPN, SAFI_EVPN, subgrp_id); + return CMD_SUCCESS; +} + DEFUN (show_bgp_updgrps_stats, show_bgp_updgrps_stats_cmd, "show [ip] bgp update-groups statistics", @@ -13606,6 +13624,7 @@ void bgp_vty_init(void) /* "show [ip] bgp summary" commands. */ install_element(VIEW_NODE, &show_bgp_instance_all_ipv6_updgrps_cmd); + install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_updgrps_cmd); install_element(VIEW_NODE, &show_bgp_instance_updgrps_stats_cmd); install_element(VIEW_NODE, &show_bgp_updgrps_stats_cmd); install_element(VIEW_NODE, &show_ip_bgp_instance_updgrps_adj_s_cmd); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 9272eae95f..be092e9501 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -769,7 +769,7 @@ static unsigned int peer_hash_key_make(void *p) return sockunion_hash(&peer->su); } -static int peer_hash_same(const void *p1, const void *p2) +static bool peer_hash_same(const void *p1, const void *p2) { const struct peer *peer1 = p1; const struct peer *peer2 = p2; @@ -6306,9 +6306,6 @@ int peer_maximum_prefix_set(struct peer *peer, afi_t afi, safi_t safi, int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi) { - struct peer *member; - struct listnode *node, *nnode; - /* Inherit configuration from peer-group if peer is member. */ if (peer_group_active(peer)) { peer_af_flag_inherit(peer, afi, safi, PEER_FLAG_MAX_PREFIX); @@ -6332,19 +6329,26 @@ int peer_maximum_prefix_unset(struct peer *peer, afi_t afi, safi_t safi) * Remove flags and configuration from all peer-group members, unless * they are explicitely overriding peer-group configuration. */ - for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) { - /* Skip peers with overridden configuration. */ - if (CHECK_FLAG(member->af_flags_override[afi][safi], - PEER_FLAG_MAX_PREFIX)) - continue; + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + struct peer *member; + struct listnode *node; - /* Remove flag and configuration on peer-group member. */ - UNSET_FLAG(member->af_flags[afi][safi], PEER_FLAG_MAX_PREFIX); - UNSET_FLAG(member->af_flags[afi][safi], - PEER_FLAG_MAX_PREFIX_WARNING); - member->pmax[afi][safi] = 0; - member->pmax_threshold[afi][safi] = 0; - member->pmax_restart[afi][safi] = 0; + for (ALL_LIST_ELEMENTS_RO(peer->group->peer, node, member)) { + /* Skip peers with overridden configuration. */ + if (CHECK_FLAG(member->af_flags_override[afi][safi], + PEER_FLAG_MAX_PREFIX)) + continue; + + /* Remove flag and configuration on peer-group member. + */ + UNSET_FLAG(member->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX); + UNSET_FLAG(member->af_flags[afi][safi], + PEER_FLAG_MAX_PREFIX_WARNING); + member->pmax[afi][safi] = 0; + member->pmax_threshold[afi][safi] = 0; + member->pmax_restart[afi][safi] = 0; + } } return 0; diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c index cb45fc8da4..e4e6760612 100644 --- a/bgpd/rfapi/bgp_rfapi_cfg.c +++ b/bgpd/rfapi/bgp_rfapi_cfg.c @@ -1601,8 +1601,10 @@ DEFUN (vnc_nve_group_export_no_prefixlist, idx += 2; /* skip afi and keyword */ if (is_bgp) { - if (idx == argc || strmatch(argv[idx]->arg, - rfg->plist_export_bgp_name[afi])) { + if (idx == argc + || (rfg->plist_export_bgp_name[afi] + && strmatch(argv[idx]->arg, + rfg->plist_export_bgp_name[afi]))) { if (rfg->plist_export_bgp_name[afi]) free(rfg->plist_export_bgp_name[afi]); rfg->plist_export_bgp_name[afi] = NULL; @@ -1612,8 +1614,9 @@ DEFUN (vnc_nve_group_export_no_prefixlist, } } else { if (idx == argc - || strmatch(argv[idx]->arg, - rfg->plist_export_zebra_name[afi])) { + || (rfg->plist_export_zebra_name[afi] + && strmatch(argv[idx]->arg, + rfg->plist_export_zebra_name[afi]))) { if (rfg->plist_export_zebra_name[afi]) free(rfg->plist_export_zebra_name[afi]); rfg->plist_export_zebra_name[afi] = NULL; @@ -1732,8 +1735,10 @@ DEFUN (vnc_nve_group_export_no_routemap, } if (is_bgp) { - if (idx == argc || strmatch(argv[idx]->arg, - rfg->routemap_export_bgp_name)) { + if (idx == argc + || (rfg->routemap_export_bgp_name + && strmatch(argv[idx]->arg, + rfg->routemap_export_bgp_name))) { if (rfg->routemap_export_bgp_name) free(rfg->routemap_export_bgp_name); rfg->routemap_export_bgp_name = NULL; @@ -1743,8 +1748,10 @@ DEFUN (vnc_nve_group_export_no_routemap, vnc_direct_bgp_reexport_group_afi(bgp, rfg, AFI_IP6); } } else { - if (idx == argc || strmatch(argv[idx]->arg, - rfg->routemap_export_zebra_name)) { + if (idx == argc + || (rfg->routemap_export_zebra_name + && strmatch(argv[idx]->arg, + rfg->routemap_export_zebra_name))) { if (rfg->routemap_export_zebra_name) free(rfg->routemap_export_zebra_name); rfg->routemap_export_zebra_name = NULL; @@ -3468,7 +3475,7 @@ DEFUN (vnc_l2_group_lni, DEFUN (vnc_l2_group_labels, vnc_l2_group_labels_cmd, - "labels LABELLIST...", + "labels (0-1048575)...", "Specify label values associated with group\n" "Space separated list of label values <0-1048575>\n") { @@ -3502,7 +3509,7 @@ DEFUN (vnc_l2_group_labels, DEFUN (vnc_l2_group_no_labels, vnc_l2_group_no_labels_cmd, - "no labels LABELLIST...", + "no labels (0-1048575)...", NO_STR "Specify label values associated with L2 group\n" "Space separated list of label values <0-1048575>\n") diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 7b304c7fbc..6f5af5182a 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -4485,7 +4485,7 @@ static void rfapiDeleteRemotePrefixesIt( struct bgp_path_info *bpi; struct bgp_path_info *next; - if (VNC_DEBUG(IMPORT_DEL_REMOTE)) { + if (p && VNC_DEBUG(IMPORT_DEL_REMOTE)) { char p1line[PREFIX_STRLEN]; char p2line[PREFIX_STRLEN]; diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index cdf281f240..1844839f25 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -4845,6 +4845,10 @@ DEFUN (add_vrf_prefix_rd_label_pref, static int rfapi_cfg_group_it_count(struct rfapi_nve_group_cfg *rfg) { int count = 0; + + if (rfg->rfapi_import_table == NULL) + return 0; + afi_t afi = AFI_MAX; while (afi-- > 0) { count += rfg->rfapi_import_table->local_count[afi]; diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 3d010e25f8..212d394fdc 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -1403,7 +1403,6 @@ static void vnc_direct_bgp_del_group_afi(struct bgp *bgp, return; } - assert(afi == AFI_IP || afi == AFI_IP6); rt = import_table->imported_vpn[afi]; if (!rfg->nves && rfg->type != RFAPI_GROUP_CFG_VRF) { diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index a57f908f62..97d520eda7 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -313,6 +313,8 @@ static void vnc_redistribute_withdraw(struct bgp *bgp, afi_t afi, uint8_t type) /* This is the per-RD table of prefixes */ table = prn->info; + if (!table) + continue; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { @@ -576,7 +578,9 @@ static void vnc_zebra_add_del_prefix(struct bgp *bgp, return; } - if (!zclient_vnc->redist[family2afi(rn->p.family)][ZEBRA_ROUTE_VNC]) + if (!vrf_bitmap_check(zclient_vnc->redist[family2afi(rn->p.family)] + [ZEBRA_ROUTE_VNC], + VRF_DEFAULT)) return; if (!bgp->rfapi_cfg) { @@ -640,7 +644,8 @@ static void vnc_zebra_add_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd, if (zclient_vnc->sock < 0) return; - if (!zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC]) + if (!vrf_bitmap_check(zclient_vnc->redist[afi][ZEBRA_ROUTE_VNC], + VRF_DEFAULT)) return; if (afi != AFI_IP && afi != AFI_IP6) { @@ -839,12 +844,12 @@ int vnc_redistribute_set(struct bgp *bgp, afi_t afi, int type) // bgp->redist[afi][type] = 1; /* Return if already redistribute flag is set. */ - if (zclient_vnc->redist[afi][type]) + if (vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT)) return CMD_WARNING_CONFIG_FAILED; vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT); - // zclient_vnc->redist[afi][type] = 1; + // vrf_bitmap_set(zclient_vnc->redist[afi][type], VRF_DEFAULT); /* Return if zebra connection is not established. */ if (zclient_vnc->sock < 0) @@ -875,9 +880,9 @@ int vnc_redistribute_unset(struct bgp *bgp, afi_t afi, int type) bgp->rfapi_cfg->redist[afi][type] = 0; /* Return if zebra connection is disabled. */ - if (!zclient_vnc->redist[afi][type]) + if (!vrf_bitmap_check(zclient_vnc->redist[afi][type], VRF_DEFAULT)) return CMD_WARNING_CONFIG_FAILED; - zclient_vnc->redist[afi][type] = 0; + vrf_bitmap_unset(zclient_vnc->redist[afi][type], VRF_DEFAULT); if (bgp->rfapi_cfg->redist[AFI_IP][type] == 0 && bgp->rfapi_cfg->redist[AFI_IP6][type] == 0 diff --git a/configure.ac b/configure.ac index 12100121d6..15bf059c89 100755 --- a/configure.ac +++ b/configure.ac @@ -323,6 +323,32 @@ fi AC_SUBST(AC_LDFLAGS) AM_CONDITIONAL([STATIC_BIN], [test "x$enable_static_bin" = "xyes"]) +dnl $AR and $RANLIB are set by LT_INIT above +AC_MSG_CHECKING([whether $AR supports D option]) +if $AR crD conftest.a; then + AC_MSG_RESULT([yes]) + dnl ARFLAGS is for automake, AR_FLAGS for libtool m-( + ARFLAGS="crD" + AR_FLAGS="crD" +else + AC_MSG_RESULT([no]) + ARFLAGS="cru" + AR_FLAGS="cru" +fi +AC_SUBST(ARFLAGS) +AC_SUBST(AR_FLAGS) + +AC_MSG_CHECKING([whether $RANLIB supports D option]) +if $RANLIB -D conftest.a; then + AC_MSG_RESULT([yes]) + RANLIB="$RANLIB -D" +else + AC_MSG_RESULT([no]) +fi +AC_SUBST(RANLIB) + +test -f conftest.a && rm conftest.a + dnl ---------------------- dnl Packages configuration dnl ---------------------- @@ -462,9 +488,9 @@ AC_ARG_ENABLE([memory-sanitizer], AS_IF([test "${enable_clippy_only}" != "yes"], [ AC_CHECK_HEADERS(json-c/json.h) AC_CHECK_LIB(json-c, json_object_get, LIBS="$LIBS -ljson-c", [], [-lm]) -if test $ac_cv_lib_json_c_json_object_get = no; then +if test "$ac_cv_lib_json_c_json_object_get" = no; then AC_CHECK_LIB(json, json_object_get, LIBS="$LIBS -ljson") - if test $ac_cv_lib_json_json_object_get = no; then + if test "$ac_cv_lib_json_json_object_get" = no; then AC_MSG_ERROR([lib json is needed to compile]) fi fi @@ -958,11 +984,6 @@ case "$host_os" in AC_CHECK_LIB(socket, main) AC_CHECK_LIB(nsl, main) AC_CHECK_LIB(umem, main) - AC_CHECK_FUNCS([printstack], [ - AC_DEFINE([HAVE_PRINTSTACK],1,[Solaris printstack]) - AC_DEFINE([HAVE_STACK_TRACE],1,[Stack symbols decode functionality]) - ]) - CURSES=-lcurses SOLARIS="solaris" ;; linux*) @@ -1028,40 +1049,47 @@ dnl --------------------- dnl Integrated VTY option dnl --------------------- case "${enable_vtysh}" in - "no") VTYSH="";; - *) VTYSH="vtysh"; - AC_DEFINE(VTYSH,,VTY shell) -dnl Vtysh uses libreadline, which looks for termcap functions at -dnl configure time. We follow readlines search order. -dnl The required procedures are in libtermcap on NetBSD, in -dnl [TODO] on Linux, and in [TODO] on Solaris. - AC_CHECK_LIB(termcap, tputs, LIBREADLINE="$LIBREADLINE -ltermcap", - [AC_CHECK_LIB(tinfo, tputs, LIBREADLINE="$LIBREADLINE -ltinfo", - [AC_CHECK_LIB(curses, tputs, LIBREADLINE="$LIBREADLINE -lcurses", - [AC_CHECK_LIB(ncurses, tputs, - LIBREADLINE="$LIBREADLINE -lncurses")] - )] - )] - ) - AC_CHECK_LIB(readline, main, LIBREADLINE="-lreadline $LIBREADLINE",, - "$LIBREADLINE") - if test $ac_cv_lib_readline_main = no; then - AC_MSG_ERROR([vtysh needs libreadline but was not found and usable on your system.]) - fi - AC_CHECK_HEADER(readline/history.h) - if test $ac_cv_header_readline_history_h = no;then - AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.]) - fi - AC_CHECK_LIB(readline, rl_completion_matches, - LIBREADLINE="$LIBREADLINE",, "$LIBREADLINE") - if test $ac_cv_lib_readline_rl_completion_matches = no; then - AC_DEFINE(rl_completion_matches,completion_matches,Old readline) - fi - AC_SEARCH_LIBS([append_history], [readline], [frr_cv_append_history=yes], [frr_cv_append_history=no]) - if test "$frr_cv_append_history" = yes; then - AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history]) - fi - ;; +"no") + VTYSH="";; +*) + VTYSH="vtysh"; + AC_DEFINE(VTYSH,,VTY shell) + + prev_libs="$LIBS" + AC_CHECK_LIB(readline, main, [ + LIBREADLINE="-lreadline" + ], [ + dnl readline failed - it might be incorrectly linked and missing its + dnl termcap/tinfo/curses dependency. see if we can fix that... + AC_SEARCH_LIBS(tputs, [termcap tinfo curses ncurses], [ + LIBREADLINE="$ac_cv_search_tputs" + ], [ + AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies]) + ]) + + dnl re-try with the lib we found above + unset ac_cv_lib_readline_main + AC_CHECK_LIB(readline, main, [ + LIBREADLINE="-lreadline $LIBREADLINE" + ], [ + AC_MSG_ERROR([libreadline (needed for vtysh) not found and/or missing dependencies]) + ], [$LIBREADLINE]) + ], []) + LIBS="$prev_libs" + + AC_CHECK_HEADER(readline/history.h) + if test $ac_cv_header_readline_history_h = no;then + AC_MSG_ERROR([readline is too old to have readline/history.h, please update to the latest readline library.]) + fi + AC_CHECK_LIB(readline, rl_completion_matches, [true], [], [$LIBREADLINE]) + if test $ac_cv_lib_readline_rl_completion_matches = no; then + AC_DEFINE(rl_completion_matches,completion_matches,Old readline) + fi + AC_CHECK_LIB(readline, [append_history], [frr_cv_append_history=yes], [frr_cv_append_history=no], [$LIBREADLINE]) + if test "$frr_cv_append_history" = yes; then + AC_DEFINE(HAVE_APPEND_HISTORY, 1, [Have history.h append_history]) + fi + ;; esac AC_SUBST(LIBREADLINE) AM_CONDITIONAL(VTYSH, test "x$VTYSH" = "xvtysh") @@ -1402,7 +1430,7 @@ fi AM_CONDITIONAL(BFDD, [test "x$BFDD" = "xbfdd"]) -if test $ac_cv_lib_json_c_json_object_get = no -a "x$BFDD" = "xbfdd"; then +if test "$ac_cv_lib_json_c_json_object_get" = no -a "x$BFDD" = "xbfdd"; then AC_MSG_ERROR(["you must use json-c library to use bfdd"]) fi @@ -1462,7 +1490,6 @@ fi AM_CONDITIONAL([ENABLE_BGP_VNC], [test x${enable_bgp_vnc} != xno]) AC_SUBST(SOLARIS) -AC_SUBST(CURSES) AC_CHECK_LIB(crypt, crypt, [], [AC_CHECK_LIB(crypto, DES_crypt)]) AC_CHECK_LIB(resolv, res_init) @@ -1811,17 +1838,31 @@ dnl check for glibc 'backtrace' dnl --------------------------- if test x"${enable_backtrace}" != x"no" ; then backtrace_ok=no - AC_CHECK_HEADER([execinfo.h], [ - AC_SEARCH_LIBS([backtrace], [execinfo], [ - AC_DEFINE(HAVE_GLIBC_BACKTRACE,,[Glibc backtrace]) - AC_DEFINE(HAVE_STACK_TRACE,,[Stack symbol decoding]) - backtrace_ok=yes - ],, [-lm]) + PKG_CHECK_MODULES([UNWIND], [libunwind], [ + AC_DEFINE(HAVE_LIBUNWIND, 1, [libunwind]) + backtrace_ok=yes + ], [ + case "$host_os" in + sunos* | solaris2*) + AC_CHECK_FUNCS([printstack], [ + AC_DEFINE([HAVE_PRINTSTACK], 1, [Solaris printstack]) + backtrace_ok=yes + ]) + ;; + esac + if test "$backtrace_ok" = no; then + AC_CHECK_HEADER([execinfo.h], [ + AC_SEARCH_LIBS([backtrace], [execinfo], [ + AC_DEFINE(HAVE_GLIBC_BACKTRACE, 1, [Glibc backtrace]) + backtrace_ok=yes + ],, [-lm]) + ]) + fi ]) if test x"${enable_backtrace}" = x"yes" -a x"${backtrace_ok}" = x"no"; then dnl user explicitly requested backtrace but we failed to find support - AC_MSG_FAILURE([failed to find backtrace support]) + AC_MSG_FAILURE([failed to find backtrace or libunwind support]) fi fi diff --git a/debianpkg/control b/debianpkg/control index 71c412a960..ea977937bf 100644 --- a/debianpkg/control +++ b/debianpkg/control @@ -4,7 +4,7 @@ Priority: optional Maintainer: Nobody <nobody@frrouting.org> Uploaders: Nobody <nobody@frrouting.org> XSBC-Original-Maintainer: <maintainers@frrouting.org> -Build-Depends: debhelper (>= 7.0.50~), libncurses5-dev, libreadline-dev, texlive-latex-base, texlive-generic-recommended, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7), python-ipaddr, python-sphinx, libpython-dev, install-info +Build-Depends: debhelper (>= 7.0.50~), libreadline-dev, libpam0g-dev | libpam-dev, libcap-dev, texinfo (>= 4.7), autotools-dev, libpcre3-dev, gawk, chrpath, libsnmp-dev, git, dh-autoreconf, libjson-c-dev, libjson-c2 | libjson-c3, dh-systemd, libsystemd-dev, bison, flex, libc-ares-dev, pkg-config, python (>= 2.7) | python3, python-sphinx | python3-sphinx, libpython-dev | libpython3-dev, install-info Standards-Version: 3.9.6 Homepage: http://www.frrouting.org/ diff --git a/debianpkg/frr.dirs b/debianpkg/frr.dirs index 56699b2daa..f3fff26441 100644 --- a/debianpkg/frr.dirs +++ b/debianpkg/frr.dirs @@ -4,5 +4,4 @@ etc/iproute2/rt_protos.d/ usr/share/doc/frr/ usr/share/doc/frr/examples/ usr/share/lintian/overrides/ -usr/share/snmp/mibs/ var/log/frr/ diff --git a/debianpkg/frr.install b/debianpkg/frr.install index 20a58bb0e9..e430868fe3 100644 --- a/debianpkg/frr.install +++ b/debianpkg/frr.install @@ -5,7 +5,6 @@ usr/include/frr/ usr/lib/ tools/frr usr/lib/frr usr/share/doc/frr/ -usr/share/snmp/mibs/ tools/etc/* etc/ tools/*.service lib/systemd/system tools/frr-reload usr/lib/frr/ diff --git a/debianpkg/rules b/debianpkg/rules index 811d45bc0b..894cd7f198 100755 --- a/debianpkg/rules +++ b/debianpkg/rules @@ -7,15 +7,15 @@ # The following are the defaults. They can be overridden by setting a # env variable to a different value -WANT_LDP ?= 1 -WANT_PIM ?= 1 +# -Werror - don't enable this unless you're doing a dev package build +WANT_WERROR ?= 0 + WANT_OSPFAPI ?= 1 WANT_BGP_VNC ?= 1 WANT_CUMULUS_MODE ?= 0 WANT_MULTIPATH ?= 1 WANT_SNMP ?= 0 WANT_RPKI ?= 0 -WANT_BFD ?= 1 # NOTES: # @@ -39,6 +39,7 @@ WANT_FRR_USER ?= frr WANT_FRR_VTY_GROUP ?= frrvty # Don't build PDF docs by default +# add build deps: texlive-latex-base, texlive-generic-recommended GENERATE_PDF ?= 0 # @@ -56,18 +57,6 @@ else $(warning "DEBIAN: SNMP disabled, see README.Debian") endif -ifeq ($(WANT_LDP), 1) - USE_LDP=--enable-ldpd -else - USE_LDP=--disable-ldpd -endif - -ifeq ($(WANT_PIM), 1) - USE_PIM=--enable-pimd -else - USE_PIM=--disable-pimd -endif - ifeq ($(WANT_OSPFAPI), 1) USE_OSPFAPI=--enable-ospfapi=yes else @@ -102,10 +91,10 @@ else USE_RPKI=--disable-rpki endif -ifeq ($(WANT_BFD), 1) - USE_BFD=--enable-bfdd +ifeq ($(WANT_WERROR), 1) + USE_WERROR=--enable-werror else - USE_BFD=--disable-bfdd + USE_WERROR=--disable-werror endif ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) @@ -127,14 +116,6 @@ else endif override_dh_auto_configure: - # Frr needs /proc to check some BSD vs Linux specific stuff. - # Else it fails with an obscure error message pointing out that - # IPCTL_FORWARDING is an undefined symbol which is not very helpful. - @if ! [ -d /proc/1 ]; then \ - echo "./configure needs a mounted /proc"; \ - exit 1; \ - fi - if ! [ -e config.status ]; then \ dh_auto_configure -- \ --enable-exampledir=/usr/share/doc/frr/examples/ \ @@ -144,32 +125,23 @@ override_dh_auto_configure: $(USE_SNMP) \ $(USE_OSPFAPI) \ $(USE_MULTIPATH) \ - $(USE_LDP) \ --enable-fpm \ $(USE_FRR_USER) $(USE_FRR_GROUP) \ $(USE_FRR_VTY_GROUP) \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-werror \ + $(USE_WERROR) \ --with-libpam \ --enable-systemd=yes \ - --enable-poll=yes \ $(USE_CUMULUS) \ - $(USE_PIM) \ - --enable-dependency-tracking \ + --disable-dependency-tracking \ $(USE_BGP_VNC) \ $(USE_RPKI) \ - $(USE_BFD) \ $(shell dpkg-buildflags --export=configure); \ fi override_dh_auto_build: - # doc/ is a bit crazy -ifeq ($(GENERATE_PDF), 1) - dh_auto_build -- -C doc pdf -endif - rm -vf doc/user/_build/texinfo/frr.info - dh_auto_build -- -C doc info + dh_auto_build override_dh_auto_test: @@ -186,12 +158,9 @@ override_dh_auto_install: mkdir -p debian/tmp/etc/frr/ perl -pi -e 's#^!log file #!log file /var/log/frr/#' debian/tmp/usr/share/doc/frr/examples/*sample* - # leftover from previously shipping SMUX client OID MIB - mkdir -p debian/tmp/usr/share/snmp/mibs/ - - # cleaning .la files - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/*.la - sed -i "/dependency_libs/ s/'.*'/''/" debian/tmp/usr/lib/frr/modules/*.la + # we don't need .la files + rm debian/tmp/usr/lib/*.la + rm debian/tmp/usr/lib/frr/modules/*.la override_dh_systemd_start: dh_systemd_start frr.service diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 7951efe5a1..76c8087f2d 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -105,7 +105,7 @@ static unsigned neighbor_entry_hash_key(void *np) return jhash(n->vertex->N.id, ISIS_SYS_ID_LEN, 0x55aa5a5a); } -static int neighbor_entry_hash_cmp(const void *a, const void *b) +static bool neighbor_entry_hash_cmp(const void *a, const void *b) { const struct neighbor_entry *na = a, *nb = b; diff --git a/isisd/isis_spf_private.h b/isisd/isis_spf_private.h index 131fa37991..3a05df3f14 100644 --- a/isisd/isis_spf_private.h +++ b/isisd/isis_spf_private.h @@ -95,16 +95,16 @@ static unsigned isis_vertex_queue_hash_key(void *vp) } __attribute__((__unused__)) -static int isis_vertex_queue_hash_cmp(const void *a, const void *b) +static bool isis_vertex_queue_hash_cmp(const void *a, const void *b) { const struct isis_vertex *va = a, *vb = b; if (va->type != vb->type) - return 0; + return false; if (VTYPE_IP(va->type)) { if (prefix_cmp(&va->N.ip.dest, &vb->N.ip.dest)) - return 0; + return false; return prefix_cmp((const struct prefix *)&va->N.ip.src, (const struct prefix *)&vb->N.ip.src) == 0; diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index 32427628ad..fe67a3f4d1 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -58,18 +58,18 @@ static unsigned tx_queue_hash_key(void *p) return jhash_1word(e->lsp->level, id_key); } -static int tx_queue_hash_cmp(const void *a, const void *b) +static bool tx_queue_hash_cmp(const void *a, const void *b) { const struct isis_tx_queue_entry *ea = a, *eb = b; if (ea->lsp->level != eb->lsp->level) - return 0; + return false; if (memcmp(ea->lsp->hdr.lsp_id, eb->lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 2)) - return 0; + return false; - return 1; + return true; } struct isis_tx_queue *isis_tx_queue_new(void *arg, diff --git a/lib/command.c b/lib/command.c index 60c5f4e75b..839c37b102 100644 --- a/lib/command.c +++ b/lib/command.c @@ -337,7 +337,7 @@ static unsigned int cmd_hash_key(void *p) return jhash(p, size, 0); } -static int cmd_hash_cmp(const void *a, const void *b) +static bool cmd_hash_cmp(const void *a, const void *b) { return a == b; } @@ -1281,7 +1281,8 @@ int cmd_execute(struct vty *vty, const char *cmd, * as to why no command could be executed. */ int command_config_read_one_line(struct vty *vty, - const struct cmd_element **cmd, int use_daemon) + const struct cmd_element **cmd, + uint32_t line_num, int use_daemon) { vector vline; int saved_node; @@ -1322,8 +1323,16 @@ int command_config_read_one_line(struct vty *vty, } } - if (ret != CMD_SUCCESS && ret != CMD_WARNING) - memcpy(vty->error_buf, vty->buf, VTY_BUFSIZ); + if (ret != CMD_SUCCESS && ret != CMD_WARNING) { + struct vty_error *ve = XCALLOC(MTYPE_TMP, sizeof(*ve)); + + memcpy(ve->error_buf, vty->buf, VTY_BUFSIZ); + ve->line_num = line_num; + if (!vty->error) + vty->error = list_new(); + + listnode_add(vty->error, ve); + } cmd_free_strvec(vline); @@ -1337,10 +1346,9 @@ int config_from_file(struct vty *vty, FILE *fp, unsigned int *line_num) *line_num = 0; while (fgets(vty->buf, VTY_BUFSIZ, fp)) { - if (!error_ret) - ++(*line_num); + ++(*line_num); - ret = command_config_read_one_line(vty, NULL, 0); + ret = command_config_read_one_line(vty, NULL, *line_num, 0); if (ret != CMD_SUCCESS && ret != CMD_WARNING && ret != CMD_ERR_NOTHING_TODO) diff --git a/lib/command.h b/lib/command.h index 8e51641b88..fbff1e67f4 100644 --- a/lib/command.h +++ b/lib/command.h @@ -419,7 +419,7 @@ extern char **cmd_complete_command(vector, struct vty *, int *status); extern const char *cmd_prompt(enum node_type); extern int command_config_read_one_line(struct vty *vty, const struct cmd_element **, - int use_config_node); + uint32_t line_num, int use_config_node); extern int config_from_file(struct vty *, FILE *, unsigned int *line_num); extern enum node_type node_parent(enum node_type); /* diff --git a/lib/distribute.c b/lib/distribute.c index 25fcd92580..0f1d666aeb 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -140,15 +140,15 @@ static unsigned int distribute_hash_make(void *arg) /* If two distribute-list have same value then return 1 else return 0. This function is used by hash package. */ -static int distribute_cmp(const struct distribute *dist1, +static bool distribute_cmp(const struct distribute *dist1, const struct distribute *dist2) { if (dist1->ifname && dist2->ifname) if (strcmp(dist1->ifname, dist2->ifname) == 0) - return 1; + return true; if (!dist1->ifname && !dist2->ifname) - return 1; - return 0; + return true; + return false; } /* Set access-list name to the distribute list. */ @@ -521,7 +521,7 @@ void distribute_list_init(int node) { disthash = hash_create( distribute_hash_make, - (int (*)(const void *, const void *))distribute_cmp, NULL); + (bool (*)(const void *, const void *))distribute_cmp, NULL); /* vtysh command-extraction doesn't grok install_element(node, ) */ if (node == RIP_NODE) { diff --git a/lib/ferr.c b/lib/ferr.c index bf89cc7f46..e18597afb0 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -64,7 +64,7 @@ static void err_key_fini(void) pthread_mutex_t refs_mtx = PTHREAD_MUTEX_INITIALIZER; struct hash *refs; -static int ferr_hash_cmp(const void *a, const void *b) +static bool ferr_hash_cmp(const void *a, const void *b) { const struct log_ref *f_a = a; const struct log_ref *f_b = b; diff --git a/lib/hash.c b/lib/hash.c index 114522a75a..641c751368 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -38,7 +38,7 @@ static struct list *_hashes; struct hash *hash_create_size(unsigned int size, unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name) { struct hash *hash; @@ -67,7 +67,7 @@ struct hash *hash_create_size(unsigned int size, } struct hash *hash_create(unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name) { return hash_create_size(HASH_INITIAL_SIZE, hash_key, hash_cmp, name); diff --git a/lib/hash.h b/lib/hash.h index 2b4ea48f38..45ae6ce60a 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -73,7 +73,7 @@ struct hash { unsigned int (*hash_key)(void *); /* Data compare function. */ - int (*hash_cmp)(const void *, const void *); + bool (*hash_cmp)(const void *, const void *); /* Backet alloc. */ unsigned long count; @@ -115,7 +115,7 @@ struct hash { * a new hash table */ extern struct hash *hash_create(unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), + bool (*hash_cmp)(const void *, const void *), const char *name); /* @@ -150,7 +150,8 @@ extern struct hash *hash_create(unsigned int (*hash_key)(void *), */ extern struct hash * hash_create_size(unsigned int size, unsigned int (*hash_key)(void *), - int (*hash_cmp)(const void *, const void *), const char *name); + bool (*hash_cmp)(const void *, const void *), + const char *name); /* * Retrieve or insert data from / into a hash table. diff --git a/lib/if_rmap.c b/lib/if_rmap.c index 2c686ecb85..108ab7ec6b 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -117,7 +117,7 @@ static unsigned int if_rmap_hash_make(void *data) return string_hash_make(if_rmap->ifname); } -static int if_rmap_hash_cmp(const void *arg1, const void *arg2) +static bool if_rmap_hash_cmp(const void *arg1, const void *arg2) { const struct if_rmap *if_rmap1 = arg1; const struct if_rmap *if_rmap2 = arg2; @@ -38,6 +38,12 @@ #include <ucontext.h> #endif +#ifdef HAVE_LIBUNWIND +#define UNW_LOCAL_ONLY +#include <libunwind.h> +#include <dlfcn.h> +#endif + DEFINE_MTYPE_STATIC(LIB, ZLOG, "Logging") static int logfile_fd = -1; /* Used in signal handler. */ @@ -313,7 +319,9 @@ static char *num_append(char *s, int len, unsigned long x) return str_append(s, len, t); } -#if defined(SA_SIGINFO) || defined(HAVE_STACK_TRACE) +#if defined(SA_SIGINFO) \ + || defined(HAVE_PRINTSTACK) \ + || defined(HAVE_GLIBC_BACKTRACE) static char *hex_append(char *s, int len, unsigned long x) { char buf[30]; @@ -533,7 +541,37 @@ void zlog_signal(int signo, const char *action Needs to be enhanced to support syslog logging. */ void zlog_backtrace_sigsafe(int priority, void *program_counter) { -#ifdef HAVE_STACK_TRACE +#ifdef HAVE_LIBUNWIND + char buf[100]; + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t ip, off, sp; + Dl_info dlinfo; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + while (unw_step(&cursor) > 0) { + char name[128] = "?"; + + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + if (unw_is_signal_frame(&cursor)) + dprintf(2, " ---- signal ----\n"); + + if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off)) { + snprintf(name, sizeof(name), "%s+%#lx", + buf, (long)off); + } + dprintf(2, "%-30s %16lx %16lx", name, (long)ip, (long)sp); + if (dladdr((void *)ip, &dlinfo)) { + dprintf(2, " %s (mapped at %p)", + dlinfo.dli_fname, dlinfo.dli_fbase); + } + dprintf(2, "\n"); + + } +#elif defined(HAVE_GLIBC_BACKTRACE) || defined(HAVE_PRINTSTACK) static const char pclabel[] = "Program counter: "; void *array[64]; int size; @@ -624,9 +662,38 @@ void zlog_backtrace_sigsafe(int priority, void *program_counter) void zlog_backtrace(int priority) { -#ifndef HAVE_GLIBC_BACKTRACE - zlog(priority, "No backtrace available on this platform."); -#else +#ifdef HAVE_LIBUNWIND + char buf[100]; + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t ip, off, sp; + Dl_info dlinfo; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + zlog(priority, "Backtrace:"); + while (unw_step(&cursor) > 0) { + char name[128] = "?"; + + unw_get_reg(&cursor, UNW_REG_IP, &ip); + unw_get_reg(&cursor, UNW_REG_SP, &sp); + + if (unw_is_signal_frame(&cursor)) + zlog(priority, " ---- signal ----"); + + if (!unw_get_proc_name(&cursor, buf, sizeof(buf), &off)) + snprintf(name, sizeof(name), "%s+%#lx", + buf, (long)off); + + if (dladdr((void *)ip, &dlinfo)) + zlog(priority, "%-30s %16lx %16lx %s (mapped at %p)", + name, (long)ip, (long)sp, + dlinfo.dli_fname, dlinfo.dli_fbase); + else + zlog(priority, "%-30s %16lx %16lx", + name, (long)ip, (long)sp); + } +#elif defined(HAVE_GLIBC_BACKTRACE) void *array[20]; int size, i; char **strings; @@ -651,7 +718,9 @@ void zlog_backtrace(int priority) zlog(priority, "[bt %d] %s", i, strings[i]); free(strings); } -#endif /* HAVE_GLIBC_BACKTRACE */ +#else /* !HAVE_GLIBC_BACKTRACE && !HAVE_LIBUNWIND */ + zlog(priority, "No backtrace available on this platform."); +#endif } void zlog(int priority, const char *format, ...) diff --git a/lib/qobj.c b/lib/qobj.c index c3f1a27c82..811645f3c3 100644 --- a/lib/qobj.c +++ b/lib/qobj.c @@ -36,7 +36,7 @@ static unsigned int qobj_key(void *data) return (unsigned int)node->nid; } -static int qobj_cmp(const void *a, const void *b) +static bool qobj_cmp(const void *a, const void *b) { const struct qobj_node *na = a, *nb = b; return na->nid == nb->nid; diff --git a/lib/routemap.c b/lib/routemap.c index 3a20ed5cda..5c6d106d83 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -631,7 +631,7 @@ static unsigned int route_map_hash_key_make(void *p) return string_hash_make(map->name); } -static int route_map_hash_cmp(const void *p1, const void *p2) +static bool route_map_hash_cmp(const void *p1, const void *p2) { const struct route_map *map1 = p1; const struct route_map *map2 = p2; @@ -639,14 +639,14 @@ static int route_map_hash_cmp(const void *p1, const void *p2) if (map1->deleted == map2->deleted) { if (map1->name && map2->name) { if (!strcmp(map1->name, map2->name)) { - return 1; + return true; } } else if (!map1->name && !map2->name) { - return 1; + return true; } } - return 0; + return false; } enum route_map_upd8_type { @@ -676,7 +676,6 @@ struct route_map_dep { struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; static unsigned int route_map_dep_hash_make_key(void *p); -static int route_map_dep_hash_cmp(const void *p1, const void *p2); static void route_map_clear_all_references(char *rmap_name); static void route_map_rule_delete(struct route_map_rule_list *, struct route_map_rule *); @@ -1624,12 +1623,12 @@ void route_map_event_hook(void (*func)(route_map_event_t, const char *)) } /* Routines for route map dependency lists and dependency processing */ -static int route_map_rmap_hash_cmp(const void *p1, const void *p2) +static bool route_map_rmap_hash_cmp(const void *p1, const void *p2) { return (strcmp((const char *)p1, (const char *)p2) == 0); } -static int route_map_dep_hash_cmp(const void *p1, const void *p2) +static bool route_map_dep_hash_cmp(const void *p1, const void *p2) { return (strcmp(((const struct route_map_dep *)p1)->dep_name, @@ -2251,7 +2250,8 @@ DEFUN(no_match_ipv6_next_hop_type, no_match_ipv6_next_hop_type_cmd, if (rmap_match_set_hook.no_match_ipv6_next_hop_type) return rmap_match_set_hook.no_match_ipv6_next_hop_type( - vty, index, "ipv6 next-hop type", argv[idx_word]->arg, + vty, index, "ipv6 next-hop type", + (argc <= idx_word) ? NULL : argv[idx_word]->arg, RMAP_EVENT_MATCH_DELETED); return CMD_SUCCESS; } diff --git a/lib/subdir.am b/lib/subdir.am index dd2731f74c..eef00a9086 100644 --- a/lib/subdir.am +++ b/lib/subdir.am @@ -3,7 +3,7 @@ # lib_LTLIBRARIES += lib/libfrr.la lib_libfrr_la_LDFLAGS = -version-info 0:0:0 -Xlinker -e_libfrr_version -lib_libfrr_la_LIBADD = @LIBCAP@ +lib_libfrr_la_LIBADD = @LIBCAP@ $(UNWIND_LIBS) lib_libfrr_la_SOURCES = \ lib/agg_table.c \ diff --git a/lib/table.c b/lib/table.c index 3adb793891..0026b7692b 100644 --- a/lib/table.c +++ b/lib/table.c @@ -33,7 +33,7 @@ DEFINE_MTYPE(LIB, ROUTE_NODE, "Route node") static void route_table_free(struct route_table *); -static int route_table_hash_cmp(const void *a, const void *b) +static bool route_table_hash_cmp(const void *a, const void *b) { const struct prefix *pa = a, *pb = b; return prefix_cmp(pa, pb) == 0; diff --git a/lib/thread.c b/lib/thread.c index 267dcd1cfc..d104c4f598 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -68,7 +68,7 @@ static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) return jhash(&a->func, size, 0); } -static int cpu_record_hash_cmp(const struct cpu_thread_history *a, +static bool cpu_record_hash_cmp(const struct cpu_thread_history *a, const struct cpu_thread_history *b) { return a->func == b->func; @@ -434,7 +434,7 @@ struct thread_master *thread_master_create(const char *name) rv->cpu_record = hash_create_size( 8, (unsigned int (*)(void *))cpu_record_hash_key, - (int (*)(const void *, const void *))cpu_record_hash_cmp, + (bool (*)(const void *, const void *))cpu_record_hash_cmp, "Thread Hash"); @@ -366,7 +366,7 @@ static unsigned int vrf_hash_bitmap_key(void *data) return bit->vrf_id; } -static int vrf_hash_bitmap_cmp(const void *a, const void *b) +static bool vrf_hash_bitmap_cmp(const void *a, const void *b) { const struct vrf_bit_set *bit1 = a; const struct vrf_bit_set *bit2 = b; @@ -1695,7 +1695,6 @@ struct vty *vty_new() new->lbuf = buffer_new(0); new->obuf = buffer_new(0); /* Use default buffer size. */ new->buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); - new->error_buf = XCALLOC(MTYPE_VTY, VTY_BUFSIZ); new->max = VTY_BUFSIZ; return new; @@ -2278,6 +2277,13 @@ void vty_serv_sock(const char *addr, unsigned short port, const char *path) #endif /* VTYSH */ } +static void vty_error_delete(void *arg) +{ + struct vty_error *ve = arg; + + XFREE(MTYPE_TMP, ve); +} + /* Close vty interface. Warning: call this only from functions that will be careful not to access the vty afterwards (since it has now been freed). This is safest from top-level functions (called @@ -2329,8 +2335,10 @@ void vty_close(struct vty *vty) if (vty->buf) XFREE(MTYPE_VTY, vty->buf); - if (vty->error_buf) - XFREE(MTYPE_VTY, vty->error_buf); + if (vty->error) { + vty->error->del = vty_error_delete; + list_delete(&vty->error); + } /* Check configure. */ vty_config_unlock(vty); @@ -2368,6 +2376,8 @@ static void vty_read_file(FILE *confp) { int ret; struct vty *vty; + struct vty_error *ve; + struct listnode *node; unsigned int line_num = 0; vty = vty_new(); @@ -2417,11 +2427,13 @@ static void vty_read_file(FILE *confp) break; } - nl = strchr(vty->error_buf, '\n'); - if (nl) - *nl = '\0'; - flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", message, - line_num, vty->error_buf); + for (ALL_LIST_ELEMENTS_RO(vty->error, node, ve)) { + nl = strchr(ve->error_buf, '\n'); + if (nl) + *nl = '\0'; + flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s", + message, ve->line_num, ve->error_buf); + } } vty_close(vty); @@ -33,6 +33,11 @@ #define VTY_BUFSIZ 4096 #define VTY_MAXHIST 20 +struct vty_error { + char error_buf[VTY_BUFSIZ]; + uint32_t line_num; +}; + /* VTY struct. */ struct vty { /* File descripter of this vty. */ @@ -71,7 +76,7 @@ struct vty { char *buf; /* Command input error buffer */ - char *error_buf; + struct list *error; /* Command cursor point */ int cp; diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index f3a33eb28f..1316a4aad3 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -36,10 +36,12 @@ static unsigned int nhrp_cache_protocol_key(void *peer_data) return sockunion_hash(&p->remote_addr); } -static int nhrp_cache_protocol_cmp(const void *cache_data, const void *key_data) +static bool nhrp_cache_protocol_cmp(const void *cache_data, + const void *key_data) { const struct nhrp_cache *a = cache_data; const struct nhrp_cache *b = key_data; + return sockunion_same(&a->remote_addr, &b->remote_addr); } diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index 203d4aa98c..db2f72ac22 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -157,10 +157,11 @@ static unsigned int nhrp_peer_key(void *peer_data) return sockunion_hash(&p->vc->remote.nbma); } -static int nhrp_peer_cmp(const void *cache_data, const void *key_data) +static bool nhrp_peer_cmp(const void *cache_data, const void *key_data) { const struct nhrp_peer *a = cache_data; const struct nhrp_peer *b = key_data; + return a->ifp == b->ifp && a->vc == b->vc; } diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c index 41a87d4adb..79a655396b 100644 --- a/nhrpd/nhrp_vc.c +++ b/nhrpd/nhrp_vc.c @@ -35,10 +35,11 @@ static unsigned int nhrp_vc_key(void *peer_data) sockunion_hash(&vc->remote.nbma), 0); } -static int nhrp_vc_cmp(const void *cache_data, const void *key_data) +static bool nhrp_vc_cmp(const void *cache_data, const void *key_data) { const struct nhrp_vc *a = cache_data; const struct nhrp_vc *b = key_data; + return sockunion_same(&a->local.nbma, &b->local.nbma) && sockunion_same(&a->remote.nbma, &b->remote.nbma); } diff --git a/nhrpd/reqid.c b/nhrpd/reqid.c index e8ad518e58..08a007bdf9 100644 --- a/nhrpd/reqid.c +++ b/nhrpd/reqid.c @@ -8,9 +8,10 @@ static unsigned int nhrp_reqid_key(void *data) return r->request_id; } -static int nhrp_reqid_cmp(const void *data, const void *key) +static bool nhrp_reqid_cmp(const void *data, const void *key) { const struct nhrp_reqid *a = data, *b = key; + return a->request_id == b->request_id; } diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c index 17a30188c7..2bfa4201cb 100644 --- a/ospf6d/ospf6_interface.c +++ b/ospf6d/ospf6_interface.c @@ -1073,13 +1073,18 @@ DEFUN (show_ipv6_ospf6_interface_traffic, DEFUN (show_ipv6_ospf6_interface_ifname_prefix, show_ipv6_ospf6_interface_ifname_prefix_cmd, - "show ipv6 ospf6 interface IFNAME prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]", + "show ipv6 ospf6 interface IFNAME prefix\ + [<\ + detail\ + |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ + >]", SHOW_STR IP6_STR OSPF6_STR INTERFACE_STR IFNAME_STR "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR @@ -1111,12 +1116,17 @@ DEFUN (show_ipv6_ospf6_interface_ifname_prefix, DEFUN (show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd, - "show ipv6 ospf6 interface prefix [<X:X::X:X|X:X::X:X/M>] [<match|detail>]", + "show ipv6 ospf6 interface prefix\ + [<\ + detail\ + |<X:X::X:X|X:X::X:X/M> [<match|detail>]\ + >]", SHOW_STR IP6_STR OSPF6_STR INTERFACE_STR "Display connected prefixes to advertise\n" + "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c index 4c24f47131..bb451c239e 100644 --- a/ospf6d/ospf6_neighbor.c +++ b/ospf6d/ospf6_neighbor.c @@ -59,7 +59,11 @@ int ospf6_neighbor_cmp(void *va, void *vb) { struct ospf6_neighbor *ona = (struct ospf6_neighbor *)va; struct ospf6_neighbor *onb = (struct ospf6_neighbor *)vb; - return (ntohl(ona->router_id) < ntohl(onb->router_id) ? -1 : 1); + + if (ona->router_id == onb->router_id) + return 0; + + return (ntohl(ona->router_id) < ntohl(onb->router_id)) ? -1 : 1; } struct ospf6_neighbor *ospf6_neighbor_lookup(uint32_t router_id, diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 359d59cb58..79b4648805 100644 --- a/ospfd/ospf_packet.c +++ b/ospfd/ospf_packet.c @@ -875,11 +875,9 @@ static int ospf_write(struct thread *thread) } /* If packets still remain in queue, call write thread. */ - if (!list_isempty(ospf->oi_write_q)) { - ospf->t_write = NULL; + if (!list_isempty(ospf->oi_write_q)) thread_add_write(master, ospf_write, ospf, ospf->fd, &ospf->t_write); - } return 0; } diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index d793735003..43842e414e 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -94,7 +94,7 @@ static unsigned int sr_hash(void *p) } /* Compare 2 Router ID hash entries based on SR Node */ -static int sr_cmp(const void *p1, const void *p2) +static bool sr_cmp(const void *p1, const void *p2) { const struct sr_node *srn = p1; const struct in_addr *rid = p2; @@ -2053,6 +2053,9 @@ DEFUN (no_sr_prefix_sid, bool found = false; int rc; + if (!ospf_sr_enabled(vty)) + return CMD_WARNING_CONFIG_FAILED; + /* Get network prefix */ argv_find(argv, argc, "A.B.C.D/M", &idx); rc = str2prefix(argv[idx]->arg, &p); diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 7376e3e95b..6103bd7db5 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -69,7 +69,7 @@ static void *pbr_nhrc_hash_alloc(void *p) return nhrc; } -static int pbr_nhrc_hash_equal(const void *arg1, const void *arg2) +static bool pbr_nhrc_hash_equal(const void *arg1, const void *arg2) { const struct nexthop *nh1, *nh2; @@ -139,7 +139,7 @@ static uint32_t pbr_nh_hash_key(void *arg) return key; } -static int pbr_nh_hash_equal(const void *arg1, const void *arg2) +static bool pbr_nh_hash_equal(const void *arg1, const void *arg2) { const struct pbr_nexthop_cache *pbrnc1 = (const struct pbr_nexthop_cache *)arg1; @@ -147,25 +147,25 @@ static int pbr_nh_hash_equal(const void *arg1, const void *arg2) (const struct pbr_nexthop_cache *)arg2; if (pbrnc1->nexthop->vrf_id != pbrnc2->nexthop->vrf_id) - return 0; + return false; if (pbrnc1->nexthop->ifindex != pbrnc2->nexthop->ifindex) - return 0; + return false; if (pbrnc1->nexthop->type != pbrnc2->nexthop->type) - return 0; + return false; switch (pbrnc1->nexthop->type) { case NEXTHOP_TYPE_IFINDEX: - return 1; + return true; case NEXTHOP_TYPE_IPV4_IFINDEX: case NEXTHOP_TYPE_IPV4: return pbrnc1->nexthop->gate.ipv4.s_addr == pbrnc2->nexthop->gate.ipv4.s_addr; case NEXTHOP_TYPE_IPV6_IFINDEX: case NEXTHOP_TYPE_IPV6: - return !memcmp(&pbrnc1->nexthop->gate.ipv6, - &pbrnc2->nexthop->gate.ipv6, 16); + return !!memcmp(&pbrnc1->nexthop->gate.ipv6, + &pbrnc2->nexthop->gate.ipv6, 16); case NEXTHOP_TYPE_BLACKHOLE: return pbrnc1->nexthop->bh_type == pbrnc2->nexthop->bh_type; } @@ -173,7 +173,7 @@ static int pbr_nh_hash_equal(const void *arg1, const void *arg2) /* * We should not get here */ - return 0; + return false; } static void pbr_nhgc_delete(struct pbr_nexthop_group_cache *p) @@ -724,7 +724,7 @@ static uint32_t pbr_nhg_hash_key(void *arg) return jhash(&nhgc->name, strlen(nhgc->name), 0x52c34a96); } -static int pbr_nhg_hash_equal(const void *arg1, const void *arg2) +static bool pbr_nhg_hash_equal(const void *arg1, const void *arg2) { const struct pbr_nexthop_group_cache *nhgc1 = (const struct pbr_nexthop_group_cache *)arg1; diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 8a2efd41ad..7a19d25a7b 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -836,15 +836,15 @@ static unsigned int igmp_group_hash_key(void *arg) return jhash_1word(group->group_addr.s_addr, 0); } -static int igmp_group_hash_equal(const void *arg1, const void *arg2) +static bool igmp_group_hash_equal(const void *arg1, const void *arg2) { const struct igmp_group *g1 = (const struct igmp_group *)arg1; const struct igmp_group *g2 = (const struct igmp_group *)arg2; if (g1->group_addr.s_addr == g2->group_addr.s_addr) - return 1; + return true; - return 0; + return false; } static struct igmp_sock *igmp_sock_new(int fd, struct in_addr ifaddr, diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 9ef343a0c5..807ad2bd12 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -687,7 +687,7 @@ static unsigned int pim_msdp_sa_hash_key_make(void *p) return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); } -static int pim_msdp_sa_hash_eq(const void *p1, const void *p2) +static bool pim_msdp_sa_hash_eq(const void *p1, const void *p2) { const struct pim_msdp_sa *sa1 = p1; const struct pim_msdp_sa *sa2 = p2; @@ -1221,7 +1221,7 @@ static unsigned int pim_msdp_peer_hash_key_make(void *p) return (jhash_1word(mp->peer.s_addr, 0)); } -static int pim_msdp_peer_hash_eq(const void *p1, const void *p2) +static bool pim_msdp_peer_hash_eq(const void *p1, const void *p2) { const struct pim_msdp_peer *mp1 = p1; const struct pim_msdp_peer *mp2 = p2; diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 68f7dae128..1290bfe56b 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -79,16 +79,16 @@ static int pim_channel_oil_compare(struct channel_oil *c1, return 0; } -static int pim_oil_equal(const void *arg1, const void *arg2) +static bool pim_oil_equal(const void *arg1, const void *arg2) { const struct channel_oil *c1 = (const struct channel_oil *)arg1; const struct channel_oil *c2 = (const struct channel_oil *)arg2; if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr) && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr)) - return 1; + return true; - return 0; + return false; } static unsigned int pim_oil_hash_key(void *arg) diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index b02102c8fd..814d2e076b 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -407,7 +407,7 @@ unsigned int pim_rpf_hash_key(void *arg) return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0); } -int pim_rpf_equal(const void *arg1, const void *arg2) +bool pim_rpf_equal(const void *arg1, const void *arg2) { const struct pim_nexthop_cache *r1 = (const struct pim_nexthop_cache *)arg1; diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 78bbfc7ed9..b9fe162f21 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -57,7 +57,7 @@ enum pim_rpf_result { PIM_RPF_OK = 0, PIM_RPF_CHANGED, PIM_RPF_FAILURE }; struct pim_upstream; unsigned int pim_rpf_hash_key(void *arg); -int pim_rpf_equal(const void *arg1, const void *arg2); +bool pim_rpf_equal(const void *arg1, const void *arg2); int pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, struct in_addr addr, int neighbor_needed); diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cd6326f097..e5f5b34f2f 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1554,16 +1554,16 @@ void pim_upstream_terminate(struct pim_instance *pim) pim->upstream_sg_wheel = NULL; } -int pim_upstream_equal(const void *arg1, const void *arg2) +bool pim_upstream_equal(const void *arg1, const void *arg2) { const struct pim_upstream *up1 = (const struct pim_upstream *)arg1; const struct pim_upstream *up2 = (const struct pim_upstream *)arg2; if ((up1->sg.grp.s_addr == up2->sg.grp.s_addr) && (up1->sg.src.s_addr == up2->sg.src.s_addr)) - return 1; + return true; - return 0; + return false; } /* rfc4601:section-4.2:"Data Packet Forwarding Rules" defines diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index ba133b39dd..a347ab991c 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -223,5 +223,5 @@ void pim_upstream_spt_prefix_list_update(struct pim_instance *pim, struct prefix_list *pl); unsigned int pim_upstream_hash_key(void *arg); -int pim_upstream_equal(const void *arg1, const void *arg2); +bool pim_upstream_equal(const void *arg1, const void *arg2); #endif /* PIM_UPSTREAM_H */ diff --git a/ripd/rip_peer.c b/ripd/rip_peer.c index ae62835a74..21317915d4 100644 --- a/ripd/rip_peer.c +++ b/ripd/rip_peer.c @@ -172,7 +172,10 @@ void rip_peer_display(struct vty *vty) static int rip_peer_list_cmp(struct rip_peer *p1, struct rip_peer *p2) { - return htonl(p1->addr.s_addr) > htonl(p2->addr.s_addr); + if (p2->addr.s_addr == p1->addr.s_addr) + return 0; + + return (htonl(p1->addr.s_addr) < htonl(p2->addr.s_addr)) ? -1 : 1; } void rip_peer_init(void) diff --git a/ripngd/ripng_peer.c b/ripngd/ripng_peer.c index 2f75898482..6b2a183539 100644 --- a/ripngd/ripng_peer.c +++ b/ripngd/ripng_peer.c @@ -180,7 +180,7 @@ void ripng_peer_display(struct vty *vty) static int ripng_peer_list_cmp(struct ripng_peer *p1, struct ripng_peer *p2) { - return addr6_cmp(&p1->addr, &p2->addr) > 0; + return memcmp(&p1->addr, &p2->addr, sizeof(struct in6_addr)); } void ripng_peer_init() diff --git a/staticd/static_routes.c b/staticd/static_routes.c index ef0e6d057a..cd0330ed82 100644 --- a/staticd/static_routes.c +++ b/staticd/static_routes.c @@ -64,8 +64,8 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, const char *ifname, enum static_blackhole_type bh_type, route_tag_t tag, uint8_t distance, struct static_vrf *svrf, struct static_vrf *nh_svrf, - struct static_nh_label *snh_label, - uint32_t table_id) + struct static_nh_label *snh_label, uint32_t table_id, + bool onlink) { struct route_node *rn; struct static_route *si; @@ -104,7 +104,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, && (table_id == si->table_id) && !memcmp(&si->snh_label, snh_label, sizeof(struct static_nh_label)) - && si->bh_type == bh_type) { + && si->bh_type == bh_type && si->onlink == onlink) { route_unlock_node(rn); return 0; } @@ -129,6 +129,7 @@ int static_add_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, si->nh_vrf_id = nh_svrf->vrf->vrf_id; strcpy(si->nh_vrfname, nh_svrf->vrf->name); si->table_id = table_id; + si->onlink = onlink; if (ifname) strlcpy(si->ifname, ifname, sizeof(si->ifname)); diff --git a/staticd/static_routes.h b/staticd/static_routes.h index bb1b664378..916ddcd7eb 100644 --- a/staticd/static_routes.h +++ b/staticd/static_routes.h @@ -79,6 +79,13 @@ struct static_route { struct static_nh_label snh_label; uint32_t table_id; + + /* + * Whether to pretend the nexthop is directly attached to the specified + * link. Only meaningful when both a gateway address and interface name + * are specified. + */ + bool onlink; }; extern bool mpls_enabled; @@ -94,7 +101,7 @@ extern int static_add_route(afi_t afi, safi_t safi, uint8_t type, uint8_t distance, struct static_vrf *svrf, struct static_vrf *nh_svrf, struct static_nh_label *snh_label, - uint32_t table_id); + uint32_t table_id, bool onlink); extern int static_delete_route(afi_t afi, safi_t safi, uint8_t type, struct prefix *p, struct prefix_ipv6 *src_p, diff --git a/staticd/static_vty.c b/staticd/static_vty.c index f697969a72..28fac0c870 100644 --- a/staticd/static_vty.c +++ b/staticd/static_vty.c @@ -79,6 +79,7 @@ struct static_hold_route { char *distance_str; char *label_str; char *table_str; + bool onlink; /* processed & masked destination, used for config display */ struct prefix dest; @@ -273,7 +274,8 @@ static int static_route_leak( afi_t afi, safi_t safi, const char *negate, const char *dest_str, const char *mask_str, const char *src_str, const char *gate_str, const char *ifname, const char *flag_str, const char *tag_str, - const char *distance_str, const char *label_str, const char *table_str) + const char *distance_str, const char *label_str, const char *table_str, + bool onlink) { int ret; uint8_t distance; @@ -509,7 +511,7 @@ static int static_route_leak( if (!negate) { static_add_route(afi, safi, type, &p, src_p, gatep, ifname, bh_type, tag, distance, svrf, nh_svrf, - &snh_label, table_id); + &snh_label, table_id, onlink); /* Mark as having FRR configuration */ vrf_set_user_cfged(svrf->vrf); } else { @@ -550,10 +552,10 @@ static int static_route(struct vty *vty, afi_t afi, safi_t safi, if (!svrf) return CMD_WARNING_CONFIG_FAILED; } - return static_route_leak( - vty, svrf, svrf, afi, safi, negate, dest_str, mask_str, src_str, - gate_str, ifname, flag_str, tag_str, distance_str, label_str, - table_str); + return static_route_leak(vty, svrf, svrf, afi, safi, negate, dest_str, + mask_str, src_str, gate_str, ifname, flag_str, + tag_str, distance_str, label_str, table_str, + false); } void static_config_install_delayed_routes(struct static_vrf *svrf) @@ -578,7 +580,8 @@ void static_config_install_delayed_routes(struct static_vrf *svrf) NULL, osvrf, nh_svrf, shr->afi, shr->safi, NULL, shr->dest_str, shr->mask_str, shr->src_str, shr->gate_str, shr->ifname, shr->flag_str, shr->tag_str, - shr->distance_str, shr->label_str, shr->table_str); + shr->distance_str, shr->label_str, shr->table_str, + shr->onlink); if (installed != CMD_SUCCESS) zlog_debug( @@ -817,9 +820,10 @@ DEFPY(ip_route_blackhole_vrf, * valid. Add an assert to make it happy */ assert(prefix); - return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, - no, prefix, mask_str, NULL, NULL, NULL, - flag, tag_str, distance_str, label, table_str); + return static_route_leak(vty, svrf, svrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, NULL, NULL, flag, + tag_str, distance_str, label, table_str, + false); } DEFPY(ip_route_address_interface, @@ -835,6 +839,7 @@ DEFPY(ip_route_address_interface, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IP_STR "Establish static routes\n" @@ -851,7 +856,8 @@ DEFPY(ip_route_address_interface, MPLS_LABEL_HELPSTR "Table to configure\n" "The table number to configure\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + "Treat the nexthop as directly attached to the interface") { struct static_vrf *svrf; struct static_vrf *nh_svrf; @@ -884,10 +890,10 @@ DEFPY(ip_route_address_interface, return CMD_WARNING_CONFIG_FAILED; } - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str); + return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + !!onlink); } DEFPY(ip_route_address_interface_vrf, @@ -902,6 +908,7 @@ DEFPY(ip_route_address_interface_vrf, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IP_STR "Establish static routes\n" @@ -917,7 +924,8 @@ DEFPY(ip_route_address_interface_vrf, MPLS_LABEL_HELPSTR "Table to configure\n" "The table number to configure\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + "Treat the nexthop as directly attached to the interface") { VTY_DECLVAR_CONTEXT(vrf, vrf); const char *flag = NULL; @@ -945,10 +953,10 @@ DEFPY(ip_route_address_interface_vrf, return CMD_WARNING_CONFIG_FAILED; } - return static_route_leak( - vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, - NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str); + return static_route_leak(vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, + prefix, mask_str, NULL, gate_str, ifname, flag, + tag_str, distance_str, label, table_str, + !!onlink); } DEFPY(ip_route, @@ -1014,7 +1022,7 @@ DEFPY(ip_route, return static_route_leak( vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str); + table_str, false); } DEFPY(ip_route_vrf, @@ -1073,7 +1081,7 @@ DEFPY(ip_route_vrf, return static_route_leak( vty, svrf, nh_svrf, AFI_IP, SAFI_UNICAST, no, prefix, mask_str, NULL, gate_str, ifname, flag, tag_str, distance_str, label, - table_str); + table_str, false); } DEFPY(ipv6_route_blackhole, @@ -1159,7 +1167,7 @@ DEFPY(ipv6_route_blackhole_vrf, return static_route_leak( vty, svrf, svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, from_str, NULL, NULL, flag, tag_str, distance_str, label, - table_str); + table_str, false); } DEFPY(ipv6_route_address_interface, @@ -1174,6 +1182,7 @@ DEFPY(ipv6_route_address_interface, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IPV6_STR @@ -1190,7 +1199,8 @@ DEFPY(ipv6_route_address_interface, MPLS_LABEL_HELPSTR "Table to configure\n" "The table number to configure\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + "Treat the nexthop as directly attached to the interface") { struct static_vrf *svrf; struct static_vrf *nh_svrf; @@ -1220,7 +1230,7 @@ DEFPY(ipv6_route_address_interface, return static_route_leak( vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, from_str, gate_str, ifname, NULL, tag_str, distance_str, label, - table_str); + table_str, !!onlink); } DEFPY(ipv6_route_address_interface_vrf, @@ -1234,6 +1244,7 @@ DEFPY(ipv6_route_address_interface_vrf, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IPV6_STR @@ -1249,7 +1260,8 @@ DEFPY(ipv6_route_address_interface_vrf, MPLS_LABEL_HELPSTR "Table to configure\n" "The table number to configure\n" - VRF_CMD_HELP_STR) + VRF_CMD_HELP_STR + "Treat the nexthop as directly attached to the interface") { VTY_DECLVAR_CONTEXT(vrf, vrf); struct static_vrf *svrf = vrf->info; @@ -1274,7 +1286,7 @@ DEFPY(ipv6_route_address_interface_vrf, return static_route_leak( vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, from_str, gate_str, ifname, NULL, tag_str, distance_str, label, - table_str); + table_str, !!onlink); } DEFPY(ipv6_route, @@ -1334,7 +1346,7 @@ DEFPY(ipv6_route, return static_route_leak( vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, from_str, gate_str, ifname, NULL, tag_str, distance_str, label, - table_str); + table_str, false); } DEFPY(ipv6_route_vrf, @@ -1387,7 +1399,7 @@ DEFPY(ipv6_route_vrf, return static_route_leak( vty, svrf, nh_svrf, AFI_IP6, SAFI_UNICAST, no, prefix_str, NULL, from_str, gate_str, ifname, NULL, tag_str, distance_str, label, - table_str); + table_str, false); } DEFUN_NOSH (show_debugging_staticd, diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index c540942a8d..4e168e142c 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -234,13 +234,13 @@ static unsigned int static_nht_hash_key(void *data) return jhash_1word(nhtd->nh_vrf_id, key); } -static int static_nht_hash_cmp(const void *d1, const void *d2) +static bool static_nht_hash_cmp(const void *d1, const void *d2) { const struct static_nht_data *nhtd1 = d1; const struct static_nht_data *nhtd2 = d2; if (nhtd1->nh_vrf_id != nhtd2->nh_vrf_id) - return 0; + return false; return prefix_same(nhtd1->nh, nhtd2->nh); } @@ -364,6 +364,8 @@ extern void static_zebra_route_add(struct route_node *rn, memcpy(&api.src_prefix, src_pp, sizeof(api.src_prefix)); } SET_FLAG(api.flags, ZEBRA_FLAG_RR_USE_DISTANCE); + if (si_changed->onlink) + SET_FLAG(api.flags, ZEBRA_FLAG_ONLINK); SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP); if (si_changed->distance) { SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE); diff --git a/tests/lib/test_segv.c b/tests/lib/test_segv.c index 3c9b57f049..43ca0837d5 100644 --- a/tests/lib/test_segv.c +++ b/tests/lib/test_segv.c @@ -32,10 +32,39 @@ struct quagga_signal_t sigs[] = {}; struct thread_master *master; -static int threadfunc(struct thread *thread) +void func1(int *arg); +void func3(void); + +void func1(int *arg) { int *null = NULL; *null += 1; + *arg = 1; +} + +static void func2(size_t depth, int *arg) +{ + /* variable stack frame size */ + int buf[depth]; + for (size_t i = 0; i < depth; i++) + buf[i] = arg[i] + 1; + if (depth > 0) + func2(depth - 1, buf); + else + func1(&buf[0]); + for (size_t i = 0; i < depth; i++) + buf[i] = arg[i] + 2; +} + +void func3(void) +{ + int buf[6]; + func2(6, buf); +} + +static int threadfunc(struct thread *thread) +{ + func3(); return 0; } diff --git a/vtysh/subdir.am b/vtysh/subdir.am index 932429a87c..66a31ffff3 100644 --- a/vtysh/subdir.am +++ b/vtysh/subdir.am @@ -24,7 +24,7 @@ noinst_HEADERS += \ vtysh/vtysh_user.h \ # end -vtysh_vtysh_LDADD = lib/libfrr.la @LIBCAP@ @LIBREADLINE@ @LIBS@ @CURSES@ @LIBPAM@ +vtysh_vtysh_LDADD = lib/libfrr.la @LIBCAP@ @LIBREADLINE@ @LIBS@ @LIBPAM@ EXTRA_DIST += vtysh/extract.pl diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6a92b90813..8ed11f1876 100644 --- a/vtysh/vtysh.c +++ b/vtysh/vtysh.c @@ -856,7 +856,7 @@ int vtysh_config_from_file(struct vty *vty, FILE *fp) while (fgets(vty->buf, VTY_BUFSIZ, fp)) { lineno++; - ret = command_config_read_one_line(vty, &cmd, 1); + ret = command_config_read_one_line(vty, &cmd, lineno, 1); switch (ret) { case CMD_WARNING: diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index 0ccd3242d5..5fe0116158 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -79,7 +79,7 @@ static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, static int fec_del(zebra_fec_t *fec); static unsigned int label_hash(void *p); -static int label_cmp(const void *p1, const void *p2); +static bool label_cmp(const void *p1, const void *p2); static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); static int nhlfe_nexthop_active_ipv6(zebra_nhlfe_t *nhlfe, @@ -592,7 +592,7 @@ static unsigned int label_hash(void *p) /* * Compare 2 LSP hash entries based on in-label. */ -static int label_cmp(const void *p1, const void *p2) +static bool label_cmp(const void *p1, const void *p2) { const zebra_ile_t *ile1 = p1; const zebra_ile_t *ile2 = p2; diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 40f97765da..1a528780c1 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -164,7 +164,7 @@ uint32_t zebra_pbr_rules_hash_key(void *arg) jhash_1word(rule->rule.unique, key)); } -int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) +bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) { const struct zebra_pbr_rule *r1, *r2; @@ -172,36 +172,36 @@ int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) r2 = (const struct zebra_pbr_rule *)arg2; if (r1->rule.seq != r2->rule.seq) - return 0; + return false; if (r1->rule.priority != r2->rule.priority) - return 0; + return false; if (r1->rule.unique != r2->rule.unique) - return 0; + return false; if (r1->rule.action.table != r2->rule.action.table) - return 0; + return false; if (r1->rule.filter.src_port != r2->rule.filter.src_port) - return 0; + return false; if (r1->rule.filter.dst_port != r2->rule.filter.dst_port) - return 0; + return false; if (r1->rule.filter.fwmark != r2->rule.filter.fwmark) - return 0; + return false; if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip)) - return 0; + return false; if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip)) - return 0; + return false; if (r1->ifp != r2->ifp) - return 0; + return false; - return 1; + return true; } struct pbr_rule_unique_lookup { @@ -260,7 +260,7 @@ uint32_t zebra_pbr_ipset_hash_key(void *arg) return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de); } -int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2) +bool zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2) { const struct zebra_pbr_ipset *r1, *r2; @@ -268,13 +268,13 @@ int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2) r2 = (const struct zebra_pbr_ipset *)arg2; if (r1->type != r2->type) - return 0; + return false; if (r1->unique != r2->unique) - return 0; + return false; if (strncmp(r1->ipset_name, r2->ipset_name, ZEBRA_IPSET_NAME_SIZE)) - return 0; - return 1; + return false; + return true; } void zebra_pbr_ipset_entry_free(void *arg) @@ -313,7 +313,7 @@ uint32_t zebra_pbr_ipset_entry_hash_key(void *arg) return key; } -int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2) +bool zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2) { const struct zebra_pbr_ipset_entry *r1, *r2; @@ -321,29 +321,29 @@ int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2) r2 = (const struct zebra_pbr_ipset_entry *)arg2; if (r1->unique != r2->unique) - return 0; + return false; if (!prefix_same(&r1->src, &r2->src)) - return 0; + return false; if (!prefix_same(&r1->dst, &r2->dst)) - return 0; + return false; if (r1->src_port_min != r2->src_port_min) - return 0; + return false; if (r1->src_port_max != r2->src_port_max) - return 0; + return false; if (r1->dst_port_min != r2->dst_port_min) - return 0; + return false; if (r1->dst_port_max != r2->dst_port_max) - return 0; + return false; if (r1->proto != r2->proto) - return 0; - return 1; + return false; + return true; } void zebra_pbr_iptable_free(void *arg) @@ -389,7 +389,7 @@ uint32_t zebra_pbr_iptable_hash_key(void *arg) iptable->unique, key); } -int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2) +bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2) { const struct zebra_pbr_iptable *r1, *r2; @@ -397,31 +397,31 @@ int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2) r2 = (const struct zebra_pbr_iptable *)arg2; if (r1->type != r2->type) - return 0; + return false; if (r1->unique != r2->unique) - return 0; + return false; if (r1->filter_bm != r2->filter_bm) - return 0; + return false; if (r1->fwmark != r2->fwmark) - return 0; + return false; if (r1->action != r2->action) - return 0; + return false; if (strncmp(r1->ipset_name, r2->ipset_name, ZEBRA_IPSET_NAME_SIZE)) - return 0; + return false; if (r1->pkt_len_min != r2->pkt_len_min) - return 0; + return false; if (r1->pkt_len_max != r2->pkt_len_max) - return 0; + return false; if (r1->tcp_flags != r2->tcp_flags) - return 0; + return false; if (r1->tcp_mask_flags != r2->tcp_mask_flags) - return 0; + return false; if (r1->dscp_value != r2->dscp_value) - return 0; + return false; if (r1->fragment != r2->fragment) - return 0; - return 1; + return false; + return true; } static void *pbr_rule_alloc_intern(void *arg) diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 3311af4d26..093fcfa8b0 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -213,7 +213,7 @@ extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule); extern void zebra_pbr_rules_free(void *arg); extern uint32_t zebra_pbr_rules_hash_key(void *arg); -extern int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); +extern bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); /* has operates on 32bit pointer * and field is a string of 8bit @@ -222,15 +222,16 @@ extern int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_ipset_free(void *arg); extern uint32_t zebra_pbr_ipset_hash_key(void *arg); -extern int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2); +extern bool zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_ipset_entry_free(void *arg); extern uint32_t zebra_pbr_ipset_entry_hash_key(void *arg); -extern int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2); +extern bool zebra_pbr_ipset_entry_hash_equal(const void *arg1, + const void *arg2); extern void zebra_pbr_iptable_free(void *arg); extern uint32_t zebra_pbr_iptable_hash_key(void *arg); -extern int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2); +extern bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_init(void); extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 2192907b21..db610098f0 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -601,9 +601,20 @@ static int nexthop_active(afi_t afi, struct route_entry *re, __PRETTY_FUNCTION__); return resolved; } else { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) { + zlog_debug("\t%s: Route Type %s has not turned on recursion", + __PRETTY_FUNCTION__, + zebra_route_string(re->type)); + if (re->type == ZEBRA_ROUTE_BGP && + !CHECK_FLAG(re->flags, ZEBRA_FLAG_IBGP)) + zlog_debug("\tEBGP: see \"disable-ebgp-connected-route-check\" or \"disable-connected-check\""); + } return 0; } } + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("\t%s: Nexthop did not lookup in table", + __PRETTY_FUNCTION__); return 0; } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 5078eff590..fe182780be 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -81,7 +81,6 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, uint32_t seq, uint16_t cmd); static unsigned int neigh_hash_keymake(void *p); -static int neigh_cmp(const void *p1, const void *p2); static void *zvni_neigh_alloc(void *p); static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, struct ethaddr *mac); @@ -137,7 +136,7 @@ static void zebra_vxlan_process_l3vni_oper_up(zebra_l3vni_t *zl3vni); static void zebra_vxlan_process_l3vni_oper_down(zebra_l3vni_t *zl3vni); static unsigned int mac_hash_keymake(void *p); -static int mac_cmp(const void *p1, const void *p2); +static bool mac_cmp(const void *p1, const void *p2); static void *zvni_mac_alloc(void *p); static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr); static int zvni_mac_del(zebra_vni_t *zvni, zebra_mac_t *mac); @@ -157,7 +156,6 @@ static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac); static void zvni_install_mac_hash(struct hash_backet *backet, void *ctxt); static unsigned int vni_hash_keymake(void *p); -static int vni_hash_cmp(const void *p1, const void *p2); static void *zvni_alloc(void *p); static zebra_vni_t *zvni_lookup(vni_t vni); static zebra_vni_t *zvni_add(vni_t vni); @@ -1254,20 +1252,28 @@ static unsigned int neigh_hash_keymake(void *p) /* * Compare two neighbor hash structures. */ -static int neigh_cmp(const void *p1, const void *p2) +static bool neigh_cmp(const void *p1, const void *p2) { const zebra_neigh_t *n1 = p1; const zebra_neigh_t *n2 = p2; if (n1 == NULL && n2 == NULL) - return 1; + return true; if (n1 == NULL || n2 == NULL) - return 0; + return false; return (memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)) == 0); } +static int neigh_list_cmp(void *p1, void *p2) +{ + const zebra_neigh_t *n1 = p1; + const zebra_neigh_t *n2 = p2; + + return memcmp(&n1->ip, &n2->ip, sizeof(struct ipaddr)); +} + /* * Callback to allocate neighbor hash entry. */ @@ -2232,16 +2238,16 @@ static unsigned int mac_hash_keymake(void *p) /* * Compare two MAC addresses. */ -static int mac_cmp(const void *p1, const void *p2) +static bool mac_cmp(const void *p1, const void *p2) { const zebra_mac_t *pmac1 = p1; const zebra_mac_t *pmac2 = p2; if (pmac1 == NULL && pmac2 == NULL) - return 1; + return true; if (pmac1 == NULL || pmac2 == NULL) - return 0; + return false; return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) == 0); @@ -2275,7 +2281,7 @@ static zebra_mac_t *zvni_mac_add(zebra_vni_t *zvni, struct ethaddr *macaddr) assert(mac); mac->neigh_list = list_new(); - mac->neigh_list->cmp = (int (*)(void *, void *))neigh_cmp; + mac->neigh_list->cmp = neigh_list_cmp; return mac; } @@ -2753,7 +2759,7 @@ static unsigned int vni_hash_keymake(void *p) /* * Compare 2 VNI hash entries. */ -static int vni_hash_cmp(const void *p1, const void *p2) +static bool vni_hash_cmp(const void *p1, const void *p2) { const zebra_vni_t *zvni1 = p1; const zebra_vni_t *zvni2 = p2; @@ -2761,6 +2767,16 @@ static int vni_hash_cmp(const void *p1, const void *p2) return (zvni1->vni == zvni2->vni); } +static int vni_list_cmp(void *p1, void *p2) +{ + const zebra_vni_t *zvni1 = p1; + const zebra_vni_t *zvni2 = p2; + + if (zvni1->vni == zvni2->vni) + return 0; + return (zvni1->vni < zvni2->vni) ? -1 : 1; +} + /* * Callback to allocate VNI hash entry. */ @@ -3601,7 +3617,7 @@ static unsigned int l3vni_hash_keymake(void *p) /* * Compare 2 L3 VNI hash entries. */ -static int l3vni_hash_cmp(const void *p1, const void *p2) +static bool l3vni_hash_cmp(const void *p1, const void *p2) { const zebra_l3vni_t *zl3vni1 = p1; const zebra_l3vni_t *zl3vni2 = p2; @@ -3662,7 +3678,7 @@ static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id) zl3vni->svi_if = NULL; zl3vni->vxlan_if = NULL; zl3vni->l2vnis = list_new(); - zl3vni->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp; + zl3vni->l2vnis->cmp = vni_list_cmp; /* Create hash table for remote RMAC */ zl3vni->rmac_table = hash_create(mac_hash_keymake, mac_cmp, |
