diff --git a/.gitignore b/.gitignore index 8c62f05539..ad3e3c80e0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ /config.status /config.guess /config.sub +/config.version /ltmain.sh /stamp-h /stamp-h[0-9]* diff --git a/Makefile.am b/Makefile.am index 65aed79152..025afa5652 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` @@ -77,6 +82,7 @@ var-%: EXTRA_DIST = BUILT_SOURCES = CLEANFILES = +DISTCLEANFILES = examplesdir = $(exampledir) @@ -156,6 +162,7 @@ EXTRA_DIST += \ README.md \ m4/README.txt \ m4/libtool-whole-archive.patch \ + config.version \ \ python/clidef.py \ python/clippy/__init__.py \ @@ -210,6 +217,15 @@ EXTRA_DIST += \ noinst_HEADERS += defaults.h +clean-local: clean-python +.PHONY: clean-python +clean-python: + find -name __pycache__ -o -name .pytest_cache | xargs rm -rf + find -name "*.pyc" -o -name "*_clippy.c" | xargs rm -f + +redistclean: + $(MAKE) distclean CONFIG_CLEAN_FILES="$(filter-out $(EXTRA_DIST), $(CONFIG_CLEAN_FILES))" + indent: tools/indent.py `find sharpd bgpd eigrpd include isisd lib nhrpd ospf6d ospfd pimd qpb ripd vtysh zebra -name '*.[ch]' | grep -v include/linux` diff --git a/babeld/babel_interface.h b/babeld/babel_interface.h index 17d9bfb936..d9e2745827 100644 --- a/babeld/babel_interface.h +++ b/babeld/babel_interface.h @@ -32,7 +32,7 @@ THE SOFTWARE. #define CONFIG_NO 1 #define CONFIG_YES 2 -/* babeld interface informations */ +/* babeld interface information */ struct babel_interface { unsigned short flags; /* see below */ unsigned short cost; diff --git a/babeld/babel_main.c b/babeld/babel_main.c index d02d86f77b..f26d3a8872 100644 --- a/babeld/babel_main.c +++ b/babeld/babel_main.c @@ -385,7 +385,7 @@ show_babel_main_configuration (struct vty *vty) vty_out (vty, "state file = %s\n" "configuration file = %s\n" - "protocol informations:\n" + "protocol information:\n" " multicast address = %s\n" " port = %d\n" "vty address = %s\n" diff --git a/bfdd/bfd.c b/bfdd/bfd.c index 8d9de857f5..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; @@ -1045,7 +1040,7 @@ struct bfd_session *bfd_mhop_lookup(struct bfd_mhop_key mhop) _mhop_key(&bs, &mhop); - return hash_lookup(bfd_shop_hash, &bs); + return hash_lookup(bfd_mhop_hash, &bs); } struct bfd_vrf *bfd_vrf_lookup(int vrf_id) 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 [{multihop|local-address |interface IFNAME|vrf NAME}]", + "peer [{[multihop] local-address |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/IMPLEMENTATION.txt b/bgpd/IMPLEMENTATION.txt index 0f06359686..5822dbba82 100644 --- a/bgpd/IMPLEMENTATION.txt +++ b/bgpd/IMPLEMENTATION.txt @@ -104,8 +104,8 @@ bgp_route.[hc]: looking for data in hash table, and putting there if missing, refcnt using pointer to existing data many validity checks - get new struct bgp_info (10 words/40 bytes) - call bgp_info_add with rn and bgp_info + get new struct bgp_path_info + call bgp_path_info_add with rn and bgp_path_info call bgp_process bgp_routemap.c @@ -149,7 +149,7 @@ bgpd.c Question: How much memory does quagga's bgpd use as a function of state received from peers? -It seems that a struct bgp_info is kept for each prefix. The "struct +It seems that a struct bgp_path_info is kept for each prefix. The "struct attr *" is interned, and variables within that are interned. So, 40 bytes are kept per received prefix, plus interned shared values. This could be 36 if 'int suppress' where changed to a u_char and moved to diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index 94413117c1..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; @@ -90,9 +90,9 @@ struct bgp_advertise *bgp_advertise_new(void) void bgp_advertise_free(struct bgp_advertise *adv) { - if (adv->binfo) - bgp_info_unlock( - adv->binfo); /* bgp_advertise bgp_info reference */ + if (adv->pathi) + /* bgp_advertise bgp_path_info reference */ + bgp_path_info_unlock(adv->pathi); XFREE(MTYPE_BGP_ADVERTISE, adv); } diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index 920cca6301..1912aec1bf 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -62,7 +62,7 @@ struct bgp_advertise { struct bgp_advertise_attr *baa; /* BGP info. */ - struct bgp_info *binfo; + struct bgp_path_info *pathi; }; /* BGP adjacency out. */ @@ -113,7 +113,7 @@ struct bgp_synchronize { }; /* BGP adjacency linked list. */ -#define BGP_INFO_ADD(N, A, TYPE) \ +#define BGP_PATH_INFO_ADD(N, A, TYPE) \ do { \ (A)->prev = NULL; \ (A)->next = (N)->TYPE; \ @@ -122,7 +122,7 @@ struct bgp_synchronize { (N)->TYPE = (A); \ } while (0) -#define BGP_INFO_DEL(N, A, TYPE) \ +#define BGP_PATH_INFO_DEL(N, A, TYPE) \ do { \ if ((A)->next) \ (A)->next->prev = (A)->prev; \ @@ -132,10 +132,10 @@ struct bgp_synchronize { (N)->TYPE = (A)->next; \ } while (0) -#define BGP_ADJ_IN_ADD(N,A) BGP_INFO_ADD(N,A,adj_in) -#define BGP_ADJ_IN_DEL(N,A) BGP_INFO_DEL(N,A,adj_in) -#define BGP_ADJ_OUT_ADD(N,A) BGP_INFO_ADD(N,A,adj_out) -#define BGP_ADJ_OUT_DEL(N,A) BGP_INFO_DEL(N,A,adj_out) +#define BGP_ADJ_IN_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_in) +#define BGP_ADJ_IN_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_in) +#define BGP_ADJ_OUT_ADD(N, A) BGP_PATH_INFO_ADD(N, A, adj_out) +#define BGP_ADJ_OUT_DEL(N, A) BGP_PATH_INFO_DEL(N, A, adj_out) #define BGP_ADV_FIFO_ADD(F, N) \ do { \ @@ -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..65a46bb965 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); } @@ -837,7 +849,7 @@ void bgp_attr_undup(struct attr *new, struct attr *old) aspath_free(new->aspath); if (new->community != old->community) - community_free(new->community); + community_free(&new->community); if (new->ecommunity != old->ecommunity) ecommunity_free(&new->ecommunity); @@ -875,11 +887,8 @@ void bgp_attr_flush(struct attr *attr) aspath_free(attr->aspath); attr->aspath = NULL; } - if (attr->community && !attr->community->refcnt) { - community_free(attr->community); - attr->community = NULL; - } - + if (attr->community && !attr->community->refcnt) + community_free(&attr->community); if (attr->ecommunity && !attr->ecommunity->refcnt) ecommunity_free(&attr->ecommunity); if (attr->lcommunity && !attr->lcommunity->refcnt) @@ -1688,7 +1697,7 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args, * - for consistency in rx processing * * The following comment is to signal GCC this intention - * and supress the warning + * and suppress the warning */ /* FALLTHRU */ case BGP_ATTR_NHLEN_IPV4: @@ -2615,7 +2624,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr, return ret; } - /* If hard error occured immediately return to the caller. */ + /* If hard error occurred immediately return to the caller. */ if (ret == BGP_ATTR_PARSE_ERROR) { flog_warn(EC_BGP_ATTRIBUTE_PARSE_ERROR, "%s: Attribute %s, parse error", peer->host, 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_clist.c b/bgpd/bgp_clist.c index 3a93db1ac6..c4a20ca233 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -65,7 +65,7 @@ static void community_entry_free(struct community_entry *entry) switch (entry->style) { case COMMUNITY_LIST_STANDARD: if (entry->u.com) - community_free(entry->u.com); + community_free(&entry->u.com); break; case LARGE_COMMUNITY_LIST_STANDARD: if (entry->u.lcom) @@ -903,7 +903,7 @@ int community_list_unset(struct community_list_handler *ch, const char *name, if (com) { entry = community_list_entry_lookup(list, com, direct); - community_free(com); + community_free(&com); } else entry = community_list_entry_lookup(list, str, direct); diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index e40674d635..614e24ca4f 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -39,19 +39,19 @@ static struct community *community_new(void) } /* Free communities value. */ -void community_free(struct community *com) +void community_free(struct community **com) { - if (com->val) - XFREE(MTYPE_COMMUNITY_VAL, com->val); - if (com->str) - XFREE(MTYPE_COMMUNITY_STR, com->str); + if ((*com)->val) + XFREE(MTYPE_COMMUNITY_VAL, (*com)->val); + if ((*com)->str) + XFREE(MTYPE_COMMUNITY_STR, (*com)->str); - if (com->json) { - json_object_free(com->json); - com->json = NULL; + if ((*com)->json) { + json_object_free((*com)->json); + (*com)->json = NULL; } - XFREE(MTYPE_COMMUNITY, com); + XFREE(MTYPE_COMMUNITY, (*com)); } /* Add one community value to the community. */ @@ -498,7 +498,7 @@ struct community *community_intern(struct community *com) /* Arguemnt com is allocated temporary. So when it is not used in hash, it should be freed. */ if (find != com) - community_free(com); + community_free(&com); /* Increment refrence counter. */ find->refcnt++; @@ -524,8 +524,7 @@ void community_unintern(struct community **com) ret = (struct community *)hash_release(comhash, *com); assert(ret != NULL); - community_free(*com); - *com = NULL; + community_free(com); } } @@ -614,17 +613,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. */ @@ -874,13 +873,13 @@ struct community *community_str2com(const char *str) break; case community_token_unknown: if (com) - community_free(com); + community_free(&com); return NULL; } } while (str); com_sort = community_uniq_sort(com); - community_free(com); + community_free(&com); return com_sort; } @@ -902,7 +901,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..e1545249d7 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -68,7 +68,7 @@ struct community { /* Prototypes of communities attribute functions. */ extern void community_init(void); extern void community_finish(void); -extern void community_free(struct community *); +extern void community_free(struct community **comm); extern struct community *community_uniq_sort(struct community *); extern struct community *community_parse(uint32_t *, unsigned short); extern struct community *community_intern(struct community *); @@ -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 5ffab0bf4f..cf085e46fb 100644 --- a/bgpd/bgp_damp.c +++ b/bgpd/bgp_damp.c @@ -42,8 +42,8 @@ static struct bgp_damp_config *damp = &bgp_damp_cfg; /* Utility macro to add and delete BGP dampening information to no used list. */ -#define BGP_DAMP_LIST_ADD(N,A) BGP_INFO_ADD(N,A,no_reuse_list) -#define BGP_DAMP_LIST_DEL(N,A) BGP_INFO_DEL(N,A,no_reuse_list) +#define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list) +#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list) /* Calculate reuse list index by penalty value. */ static int bgp_reuse_index(int penalty) @@ -128,7 +128,7 @@ static int bgp_reuse_timer(struct thread *t) /* 3. if ( the saved list head pointer is non-empty ) */ for (; bdi; bdi = next) { - struct bgp *bgp = bdi->binfo->peer->bgp; + struct bgp *bgp = bdi->path->peer->bgp; next = bdi->next; @@ -145,15 +145,15 @@ static int bgp_reuse_timer(struct thread *t) /* if (figure-of-merit < reuse). */ if (bdi->penalty < damp->reuse_limit) { /* Reuse the route. */ - bgp_info_unset_flag(bdi->rn, bdi->binfo, - BGP_INFO_DAMPED); + bgp_path_info_unset_flag(bdi->rn, bdi->path, + BGP_PATH_DAMPED); bdi->suppress_time = 0; if (bdi->lastrecord == BGP_RECORD_UPDATE) { - bgp_info_unset_flag(bdi->rn, bdi->binfo, - BGP_INFO_HISTORY); + bgp_path_info_unset_flag(bdi->rn, bdi->path, + BGP_PATH_HISTORY); bgp_aggregate_increment(bgp, &bdi->rn->p, - bdi->binfo, bdi->afi, + bdi->path, bdi->afi, bdi->safi); bgp_process(bgp, bdi->rn, bdi->afi, bdi->safi); } @@ -172,8 +172,8 @@ static int bgp_reuse_timer(struct thread *t) } /* A route becomes unreachable (RFC2439 Section 4.8.2). */ -int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, - safi_t safi, int attr_change) +int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn, + afi_t afi, safi_t safi, int attr_change) { time_t t_now; struct bgp_damp_info *bdi = NULL; @@ -182,8 +182,8 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, t_now = bgp_clock(); /* Processing Unreachable Messages. */ - if (binfo->extra) - bdi = binfo->extra->damp_info; + if (path->extra) + bdi = path->extra->damp_info; if (bdi == NULL) { /* If there is no previous stability history. */ @@ -195,7 +195,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, bdi = XCALLOC(MTYPE_BGP_DAMP_INFO, sizeof(struct bgp_damp_info)); - bdi->binfo = binfo; + bdi->path = path; bdi->rn = rn; bdi->penalty = (attr_change ? DEFAULT_PENALTY / 2 : DEFAULT_PENALTY); @@ -205,7 +205,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, bdi->index = -1; bdi->afi = afi; bdi->safi = safi; - (bgp_info_extra_get(binfo))->damp_info = bdi; + (bgp_path_info_extra_get(path))->damp_info = bdi; BGP_DAMP_LIST_ADD(damp, bdi); } else { last_penalty = bdi->penalty; @@ -222,16 +222,16 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, bdi->flap++; } - assert((rn == bdi->rn) && (binfo == bdi->binfo)); + assert((rn == bdi->rn) && (path == bdi->path)); bdi->lastrecord = BGP_RECORD_WITHDRAW; bdi->t_updated = t_now; /* Make this route as historical status. */ - bgp_info_set_flag(rn, binfo, BGP_INFO_HISTORY); + bgp_path_info_set_flag(rn, path, BGP_PATH_HISTORY); /* Remove the route from a reuse list if it is on one. */ - if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED)) { + if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) { /* If decay rate isn't equal to 0, reinsert brn. */ if (bdi->penalty != last_penalty && bdi->index >= 0) { bgp_reuse_list_delete(bdi); @@ -243,7 +243,7 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, /* If not suppressed before, do annonunce this withdraw and insert into reuse_list. */ if (bdi->penalty >= damp->suppress_value) { - bgp_info_set_flag(rn, binfo, BGP_INFO_DAMPED); + bgp_path_info_set_flag(rn, path, BGP_PATH_DAMPED); bdi->suppress_time = t_now; BGP_DAMP_LIST_DEL(damp, bdi); bgp_reuse_list_add(bdi); @@ -252,28 +252,28 @@ int bgp_damp_withdraw(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, return BGP_DAMP_USED; } -int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, +int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, afi_t afi, safi_t safi) { time_t t_now; struct bgp_damp_info *bdi; int status; - if (!binfo->extra || !((bdi = binfo->extra->damp_info))) + if (!path->extra || !((bdi = path->extra->damp_info))) return BGP_DAMP_USED; t_now = bgp_clock(); - bgp_info_unset_flag(rn, binfo, BGP_INFO_HISTORY); + bgp_path_info_unset_flag(rn, path, BGP_PATH_HISTORY); bdi->lastrecord = BGP_RECORD_UPDATE; bdi->penalty = bgp_damp_decay(t_now - bdi->t_updated, bdi->penalty); - if (!CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED) + if (!CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED) && (bdi->penalty < damp->suppress_value)) status = BGP_DAMP_USED; - else if (CHECK_FLAG(bdi->binfo->flags, BGP_INFO_DAMPED) + else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED) && (bdi->penalty < damp->reuse_limit)) { - bgp_info_unset_flag(rn, binfo, BGP_INFO_DAMPED); + bgp_path_info_unset_flag(rn, path, BGP_PATH_DAMPED); bgp_reuse_list_delete(bdi); BGP_DAMP_LIST_ADD(damp, bdi); bdi->suppress_time = 0; @@ -290,28 +290,29 @@ int bgp_damp_update(struct bgp_info *binfo, struct bgp_node *rn, afi_t afi, } /* Remove dampening information and history route. */ -int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi) +int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi) { time_t t_now, t_diff; struct bgp_damp_info *bdi; - assert(binfo->extra && binfo->extra->damp_info); + assert(path->extra && path->extra->damp_info); t_now = bgp_clock(); - bdi = binfo->extra->damp_info; + bdi = path->extra->damp_info; - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) { + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) { t_diff = t_now - bdi->suppress_time; if (t_diff >= damp->max_suppress_time) { - bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_DAMPED); + bgp_path_info_unset_flag(bdi->rn, path, + BGP_PATH_DAMPED); bgp_reuse_list_delete(bdi); BGP_DAMP_LIST_ADD(damp, bdi); bdi->penalty = damp->reuse_limit; bdi->suppress_time = 0; bdi->t_updated = t_now; - /* Need to announce UPDATE once this binfo is usable + /* Need to announce UPDATE once this path is usable * again. */ if (bdi->lastrecord == BGP_RECORD_UPDATE) return 1; @@ -323,7 +324,7 @@ int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi) bdi->penalty = bgp_damp_decay(t_diff, bdi->penalty); if (bdi->penalty <= damp->reuse_limit / 2.0) { - /* release the bdi, bdi->binfo. */ + /* release the bdi, bdi->path. */ bgp_damp_info_free(bdi, 1); return 0; } else @@ -334,23 +335,24 @@ int bgp_damp_scan(struct bgp_info *binfo, afi_t afi, safi_t safi) void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw) { - struct bgp_info *binfo; + struct bgp_path_info *path; if (!bdi) return; - binfo = bdi->binfo; - binfo->extra->damp_info = NULL; + path = bdi->path; + path->extra->damp_info = NULL; - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) bgp_reuse_list_delete(bdi); else BGP_DAMP_LIST_DEL(damp, bdi); - bgp_info_unset_flag(bdi->rn, binfo, BGP_INFO_HISTORY | BGP_INFO_DAMPED); + bgp_path_info_unset_flag(bdi->rn, path, + BGP_PATH_HISTORY | BGP_PATH_DAMPED); if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) - bgp_info_delete(bdi->rn, binfo); + bgp_path_info_delete(bdi->rn, path); XFREE(MTYPE_BGP_DAMP_INFO, bdi); } @@ -446,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. */ @@ -588,7 +593,7 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf, return buf; } -void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, +void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, json_object *json_path) { struct bgp_damp_info *bdi; @@ -596,11 +601,11 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, char timebuf[BGP_UPTIME_LEN]; int penalty; - if (!binfo->extra) + if (!path->extra) return; /* BGP dampening information. */ - bdi = binfo->extra->damp_info; + bdi = path->extra->damp_info; /* If dampening is not enabled or there is no dampening information, return immediately. */ @@ -618,8 +623,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 1, json_path); - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) - && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 1, json_path); } else { @@ -629,8 +634,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, json_path)); - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) - && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, ", reuse in %s", bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN, 0, @@ -640,7 +645,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_info *binfo, } } -const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo, +const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path, char *timebuf, size_t len, bool use_json, json_object *json) { @@ -648,11 +653,11 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_info *binfo, time_t t_now, t_diff; int penalty; - if (!binfo->extra) + if (!path->extra) return NULL; /* BGP dampening information. */ - bdi = binfo->extra->damp_info; + bdi = path->extra->damp_info; /* If dampening is not enabled or there is no dampening information, return immediately. */ @@ -684,7 +689,7 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi) vty_out(vty, "Suppress penalty: %d\n", damp->suppress_value); vty_out(vty, "Max suppress time: %lld min\n", (long long)damp->max_suppress_time / 60); - vty_out(vty, "Max supress penalty: %u\n", damp->ceiling); + vty_out(vty, "Max suppress penalty: %u\n", damp->ceiling); vty_out(vty, "\n"); } else vty_out(vty, "dampening not enabled for %s\n", diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h index 8326bae697..18bf561c47 100644 --- a/bgpd/bgp_damp.h +++ b/bgpd/bgp_damp.h @@ -43,8 +43,8 @@ struct bgp_damp_info { /* Time of route start to be suppressed. */ time_t suppress_time; - /* Back reference to bgp_info. */ - struct bgp_info *binfo; + /* Back reference to bgp_path_info. */ + struct bgp_path_info *path; /* Back reference to bgp_node. */ struct bgp_node *rn; @@ -130,18 +130,19 @@ struct bgp_damp_config { extern int bgp_damp_enable(struct bgp *, afi_t, safi_t, time_t, unsigned int, unsigned int, time_t); extern int bgp_damp_disable(struct bgp *, afi_t, safi_t); -extern int bgp_damp_withdraw(struct bgp_info *, struct bgp_node *, afi_t, - safi_t, int); -extern int bgp_damp_update(struct bgp_info *, struct bgp_node *, afi_t, safi_t); -extern int bgp_damp_scan(struct bgp_info *, afi_t, safi_t); -extern void bgp_damp_info_free(struct bgp_damp_info *, int); +extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_node *rn, + afi_t afi, safi_t safi, int attr_change); +extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_node *rn, + afi_t afi, safi_t saff); +extern int bgp_damp_scan(struct bgp_path_info *path, afi_t afi, safi_t safi); +extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw); extern void bgp_damp_info_clean(void); extern int bgp_damp_decay(time_t, int); extern void bgp_config_write_damp(struct vty *); -extern void bgp_damp_info_vty(struct vty *, struct bgp_info *, +extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, json_object *json_path); extern const char *bgp_damp_reuse_time_vty(struct vty *vty, - struct bgp_info *binfo, + struct bgp_path_info *path, char *timebuf, size_t len, bool use_json, json_object *json); extern int bgp_show_dampening_parameters(struct vty *vty, afi_t, safi_t); diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c index f49f80b5d9..c7fad29cb0 100644 --- a/bgpd/bgp_debug.c +++ b/bgpd/bgp_debug.c @@ -1380,7 +1380,7 @@ DEFUN (no_debug_bgp_update_direct_peer, DEFPY (debug_bgp_update_prefix_afi_safi, debug_bgp_update_prefix_afi_safi_cmd, - "debug bgp updates prefix l2vpn$afi evpn$safi type [ip ]|multicast ip |prefix ip >", + "debug bgp updates prefix l2vpn$afi evpn$safi type [ip ]|multicast ip |prefix ip >", DEBUG_STR BGP_STR "BGP updates\n" @@ -1443,7 +1443,7 @@ DEFPY (debug_bgp_update_prefix_afi_safi, DEFPY (no_debug_bgp_update_prefix_afi_safi, no_debug_bgp_update_prefix_afi_safi_cmd, - "no debug bgp updates prefix l2vpn$afi evpn$safi type [ip ]|multicast ip |prefix ip >", + "no debug bgp updates prefix l2vpn$afi evpn$safi type [ip ]|multicast ip |prefix ip >", NO_STR DEBUG_STR BGP_STR diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c index ef746597a4..3d1880ca48 100644 --- a/bgpd/bgp_dump.c +++ b/bgpd/bgp_dump.c @@ -299,9 +299,9 @@ static void bgp_dump_routes_index_table(struct bgp *bgp) } -static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn, - struct bgp_info *info, - unsigned int seq) +static struct bgp_path_info * +bgp_dump_route_node_record(int afi, struct bgp_node *rn, + struct bgp_path_info *path, unsigned int seq) { struct stream *obuf; size_t sizep; @@ -349,18 +349,18 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn, stream_putw(obuf, 0); endp = stream_get_endp(obuf); - for (; info; info = info->next) { + for (; path; path = path->next) { size_t cur_endp; /* Peer index */ - stream_putw(obuf, info->peer->table_dump_index); + stream_putw(obuf, path->peer->table_dump_index); /* Originated */ - stream_putl(obuf, time(NULL) - (bgp_clock() - info->uptime)); + stream_putl(obuf, time(NULL) - (bgp_clock() - path->uptime)); /* Dump attribute. */ /* Skip prefix & AFI/SAFI for MP_NLRI */ - bgp_dump_routes_attr(obuf, info->attr, &rn->p); + bgp_dump_routes_attr(obuf, path->attr, &rn->p); cur_endp = stream_get_endp(obuf); if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER @@ -379,7 +379,7 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn, bgp_dump_set_size(obuf, MSG_TABLE_DUMP_V2); fwrite(STREAM_DATA(obuf), stream_get_endp(obuf), 1, bgp_dump_routes.fp); - return info; + return path; } @@ -387,7 +387,7 @@ static struct bgp_info *bgp_dump_route_node_record(int afi, struct bgp_node *rn, static unsigned int bgp_dump_routes_func(int afi, int first_run, unsigned int seq) { - struct bgp_info *info; + struct bgp_path_info *path; struct bgp_node *rn; struct bgp *bgp; struct bgp_table *table; @@ -410,9 +410,9 @@ static unsigned int bgp_dump_routes_func(int afi, int first_run, table = bgp->rib[afi][SAFI_UNICAST]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - info = rn->info; - while (info) { - info = bgp_dump_route_node_record(afi, rn, info, seq); + path = rn->info; + while (path) { + path = bgp_dump_route_node_record(afi, rn, path, seq); seq++; } } 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_errors.c b/bgpd/bgp_errors.c index 7cebd0e484..753ee6baf1 100644 --- a/bgpd/bgp_errors.c +++ b/bgpd/bgp_errors.c @@ -171,7 +171,7 @@ static struct log_ref ferr_bgp_warn[] = { }, { .code = EC_BGP_CAPABILITY_VENDOR, - .title = "BGP has recieved capability data specific to a particular vendor", + .title = "BGP has received capability data specific to a particular vendor", .description = "BGP has received a capability that is vendor specific and as such we have no knowledge of how to use this capability in FRR", .suggestion = "On peer turn off this feature" }, @@ -197,43 +197,43 @@ static struct log_ref ferr_bgp_err[] = { .code = EC_BGP_ATTR_FLAG, .title = "BGP attribute flag is incorrect", .description = "BGP attribute flag is set to the wrong value (Optional/Transitive/Partial)", - .suggestion = "Determine the soure of the attribute and determine why the attribute flag has been set incorrectly" + .suggestion = "Determine the source of the attribute and determine why the attribute flag has been set incorrectly" }, { .code = EC_BGP_ATTR_LEN, .title = "BGP attribute length is incorrect", .description = "BGP attribute length is incorrect", - .suggestion = "Determine the soure of the attribute and determine why the attribute length has been set incorrectly" + .suggestion = "Determine the source of the attribute and determine why the attribute length has been set incorrectly" }, { .code = EC_BGP_ATTR_ORIGIN, .title = "BGP attribute origin value invalid", .description = "BGP attribute origin value is invalid", - .suggestion = "Determine the soure of the attribute and determine why the origin attribute has been set incorrectly" + .suggestion = "Determine the source of the attribute and determine why the origin attribute has been set incorrectly" }, { .code = EC_BGP_ATTR_MAL_AS_PATH, .title = "BGP as path is invalid", .description = "BGP as path has been malformed", - .suggestion = "Determine the soure of the update and determine why the as path has been set incorrectly" + .suggestion = "Determine the source of the update and determine why the as path has been set incorrectly" }, { .code = EC_BGP_ATTR_FIRST_AS, .title = "BGP as path first as is invalid", .description = "BGP update has invalid first as in as path", - .suggestion = "Determine the soure of the update and determine why the as path first as value has been set incorrectly" + .suggestion = "Determine the source of the update and determine why the as path first as value has been set incorrectly" }, { .code = EC_BGP_ATTR_PMSI_TYPE, .title = "BGP PMSI tunnel attribute type is invalid", .description = "BGP update has invalid type for PMSI tunnel", - .suggestion = "Determine the soure of the update and determine why the PMSI tunnel attribute type has been set incorrectly" + .suggestion = "Determine the source of the update and determine why the PMSI tunnel attribute type has been set incorrectly" }, { .code = EC_BGP_ATTR_PMSI_LEN, .title = "BGP PMSI tunnel attribute length is invalid", .description = "BGP update has invalid length for PMSI tunnel", - .suggestion = "Determine the soure of the update and determine why the PMSI tunnel attribute length has been set incorrectly" + .suggestion = "Determine the source of the update and determine why the PMSI tunnel attribute length has been set incorrectly" }, { .code = EC_BGP_PEER_GROUP, @@ -269,7 +269,7 @@ static struct log_ref ferr_bgp_err[] = { .code = EC_BGP_JSON_MEM_ERROR, .title = "BGP unable to allocate memory for JSON output", .description = "BGP attempted to generate JSON output and was unable to allocate the memory required", - .suggestion = "Ensure that the device has adequate memory to suport the required functions" + .suggestion = "Ensure that the device has adequate memory to support the required functions" }, { .code = EC_BGP_UPDGRP_ATTR_LEN, diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index c350015cc4..574ece8cc5 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -60,10 +60,9 @@ DEFINE_QOBJ_TYPE(evpnes) /* * Static function declarations */ -static void delete_evpn_route_entry(struct bgp *bgp, - afi_t afi, safi_t safi, +static void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_node *rn, - struct bgp_info **ri); + struct bgp_path_info **pi); static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn); /* @@ -71,16 +70,12 @@ static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn); */ /* compare two IPV4 VTEP IPs */ -static int evpn_vtep_ip_cmp(const void *p1, const void *p2) +static int evpn_vtep_ip_cmp(void *p1, void *p2) { const struct in_addr *ip1 = p1; const struct in_addr *ip2 = p2; - if (!ip1 && !ip2) - return 1; - if (!ip1 || !ip2) - return 0; - return (ip1->s_addr == ip2->s_addr); + return ip1->s_addr - ip2->s_addr; } /* @@ -97,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); } @@ -123,18 +118,26 @@ 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); } +static int vni_list_cmp(void *p1, void *p2) +{ + const struct bgpevpn *vpn1 = p1; + const struct bgpevpn *vpn2 = p2; + + return vpn1->vni - vpn2->vni; +} + /* * Make vrf import route target hash key. */ @@ -149,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); } @@ -266,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); } @@ -914,10 +917,10 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, */ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, struct bgp_node *rn, - struct bgp_info *old_local) + struct bgp_path_info *old_local) { struct bgp_node *global_rn; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -929,18 +932,18 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn, (struct prefix *)&rn->p, &vpn->prd); if (global_rn) { /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry(bgp, afi, safi, global_rn, &ri); + delete_evpn_route_entry(bgp, afi, safi, global_rn, &pi); /* Schedule for processing - withdraws to peers happen from * this table. */ - if (ri) + if (pi) bgp_process(bgp, global_rn, afi, safi); bgp_unlock_node(global_rn); } /* Delete route entry in the VNI route table, caller to remove. */ - bgp_info_delete(rn, old_local); + bgp_path_info_delete(rn, old_local); } static struct in_addr *es_vtep_new(struct in_addr vtep) @@ -1030,9 +1033,9 @@ static int evpn_es_route_select_install(struct bgp *bgp, int ret = 0; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; - struct bgp_info *old_select; /* old best */ - struct bgp_info *new_select; /* new best */ - struct bgp_info_pair old_and_new; + struct bgp_path_info *old_select; /* old best */ + struct bgp_path_info *new_select; /* new best */ + struct bgp_path_info_pair old_and_new; /* Compute the best path. */ bgp_best_selection(bgp, rn, &bgp->maxpaths[afi][safi], @@ -1048,14 +1051,14 @@ static int evpn_es_route_select_install(struct bgp *bgp, && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_IMPORTED && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) - && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp->addpath_tx_used[afi][safi]) { if (bgp_zebra_has_route_changed(rn, old_select)) { ret = evpn_es_install_vtep(bgp, es, (struct prefix_evpn *)&rn->p, old_select->attr->nexthop); } - UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); + UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(rn); return ret; } @@ -1071,11 +1074,11 @@ static int evpn_es_route_select_install(struct bgp *bgp, bgp_bump_version(rn); if (old_select) - bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); + bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED); if (new_select) { - bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED); - bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED); + bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED); + UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG); } if (new_select && new_select->type == ZEBRA_ROUTE_BGP @@ -1094,9 +1097,9 @@ static int evpn_es_route_select_install(struct bgp *bgp, /* Clear any route change flags. */ bgp_zebra_clear_route_change_flags(rn); - /* Reap old select bgp_info, if it has been removed */ - if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) - bgp_info_reap(rn, old_select); + /* Reap old select bgp_path_info, if it has been removed */ + if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED)) + bgp_path_info_reap(rn, old_select); return ret; } @@ -1108,8 +1111,8 @@ static int evpn_es_route_select_install(struct bgp *bgp, static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, struct bgp_node *rn) { - struct bgp_info *old_select, *new_select; - struct bgp_info_pair old_and_new; + struct bgp_path_info *old_select, *new_select; + struct bgp_path_info_pair old_and_new; struct prefix_evpn *evp; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -1131,7 +1134,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_IMPORTED && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) - && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp->addpath_tx_used[afi][safi]) { if (bgp_zebra_has_route_changed(rn, old_select)) { if (old_select->attr->sticky) @@ -1147,7 +1150,7 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, old_select->attr->nexthop, flags, mac_mobility_seqnum(old_select->attr)); } - UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); + UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(rn); return ret; } @@ -1162,11 +1165,11 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, bgp_bump_version(rn); if (old_select) - bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); + bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED); if (new_select) { - bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED); - bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED); + bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED); + UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG); } if (new_select && new_select->type == ZEBRA_ROUTE_BGP @@ -1205,9 +1208,9 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, /* Clear any route change flags. */ bgp_zebra_clear_route_change_flags(rn); - /* Reap old select bgp_info, if it has been removed */ - if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) - bgp_info_reap(rn, old_select); + /* Reap old select bgp_path_info, if it has been removed */ + if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED)) + bgp_path_info_reap(rn, old_select); return ret; } @@ -1217,21 +1220,21 @@ static int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, */ static int evpn_route_is_def_gw(struct bgp *bgp, struct bgp_node *rn) { - struct bgp_info *tmp_ri = NULL; - struct bgp_info *local_ri = NULL; + struct bgp_path_info *tmp_pi = NULL; + struct bgp_path_info *local_pi = NULL; - local_ri = NULL; - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; + local_pi = NULL; + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) + local_pi = tmp_pi; } - if (!local_ri) + if (!local_pi) return 0; - return local_ri->attr->default_gw; + return local_pi->attr->default_gw; } @@ -1240,21 +1243,21 @@ static int evpn_route_is_def_gw(struct bgp *bgp, struct bgp_node *rn) */ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn) { - struct bgp_info *tmp_ri; - struct bgp_info *local_ri; + struct bgp_path_info *tmp_pi; + struct bgp_path_info *local_pi; - local_ri = NULL; - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; + local_pi = NULL; + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) + local_pi = tmp_pi; } - if (!local_ri) + if (!local_pi) return 0; - return local_ri->attr->sticky; + return local_pi->attr->sticky; } /* @@ -1262,20 +1265,17 @@ static int evpn_route_is_sticky(struct bgp *bgp, struct bgp_node *rn) * This could be in the ES table or the global table. * TODO: handle remote ES (type4) routes as well */ -static int update_evpn_type4_route_entry(struct bgp *bgp, - struct evpnes *es, +static int update_evpn_type4_route_entry(struct bgp *bgp, struct evpnes *es, afi_t afi, safi_t safi, - struct bgp_node *rn, - struct attr *attr, - int add, - struct bgp_info **ri, + struct bgp_node *rn, struct attr *attr, + int add, struct bgp_path_info **ri, int *route_changed) { char buf[ESI_STR_LEN]; char buf1[INET6_ADDRSTRLEN]; - struct bgp_info *tmp_ri = NULL; - struct bgp_info *local_ri = NULL; /* local route entry if any */ - struct bgp_info *remote_ri = NULL; /* remote route entry if any */ + struct bgp_path_info *tmp_pi = NULL; + struct bgp_path_info *local_pi = NULL; /* local route entry if any */ + struct bgp_path_info *remote_pi = NULL; /* remote route entry if any */ struct attr *attr_new = NULL; struct prefix_evpn *evp = NULL; @@ -1284,22 +1284,22 @@ static int update_evpn_type4_route_entry(struct bgp *bgp, evp = (struct prefix_evpn *)&rn->p; /* locate the local and remote entries if any */ - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp->peer_self && - tmp_ri->type == ZEBRA_ROUTE_BGP && - tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; - if (tmp_ri->type == ZEBRA_ROUTE_BGP && - tmp_ri->sub_type == BGP_ROUTE_IMPORTED && - CHECK_FLAG(tmp_ri->flags, BGP_INFO_VALID)) - remote_ri = tmp_ri; + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) + local_pi = tmp_pi; + if (tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_IMPORTED + && CHECK_FLAG(tmp_pi->flags, BGP_PATH_VALID)) + remote_pi = tmp_pi; } - /* we don't expect to see a remote_ri at this point. + /* we don't expect to see a remote_pi at this point. * An ES route has esi + vtep_ip as the key, * We shouldn't see the same route from any other vtep. */ - if (remote_ri) { + if (remote_pi) { flog_err( EC_BGP_ES_INVALID, "%u ERROR: local es route for ESI: %s Vtep %s also learnt from remote", @@ -1309,46 +1309,47 @@ static int update_evpn_type4_route_entry(struct bgp *bgp, return -1; } - if (!local_ri && !add) + if (!local_pi && !add) return 0; /* create or update the entry */ - if (!local_ri) { + if (!local_pi) { /* Add or update attribute to hash */ attr_new = bgp_attr_intern(attr); /* Create new route with its attribute. */ - tmp_ri = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, - 0, bgp->peer_self, attr_new, rn); - SET_FLAG(tmp_ri->flags, BGP_INFO_VALID); + tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, + bgp->peer_self, attr_new, rn); + SET_FLAG(tmp_pi->flags, BGP_PATH_VALID); /* add the newly created path to the route-node */ - bgp_info_add(rn, tmp_ri); + bgp_path_info_add(rn, tmp_pi); } else { - tmp_ri = local_ri; - if (attrhash_cmp(tmp_ri->attr, attr) - && !CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) + tmp_pi = local_pi; + if (attrhash_cmp(tmp_pi->attr, attr) + && !CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED)) *route_changed = 0; else { /* The attribute has changed. * Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(attr); - bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, tmp_pi, + BGP_PATH_ATTR_CHANGED); /* Restore route, if needed. */ - if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, tmp_ri); + if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, tmp_pi); /* Unintern existing, set to new. */ - bgp_attr_unintern(&tmp_ri->attr); - tmp_ri->attr = attr_new; - tmp_ri->uptime = bgp_clock(); + bgp_attr_unintern(&tmp_pi->attr); + tmp_pi->attr = attr_new; + tmp_pi->uptime = bgp_clock(); } } /* Return back the route entry. */ - *ri = tmp_ri; + *ri = tmp_pi; return 0; } @@ -1366,7 +1367,7 @@ static int update_evpn_type4_route(struct bgp *bgp, struct attr attr; struct attr *attr_new = NULL; struct bgp_node *rn = NULL; - struct bgp_info *ri = NULL; + struct bgp_path_info *pi = NULL; memset(&attr, 0, sizeof(struct attr)); @@ -1384,9 +1385,8 @@ static int update_evpn_type4_route(struct bgp *bgp, rn = bgp_node_get(es->route_table, (struct prefix *)p); /* Create or update route entry. */ - ret = update_evpn_type4_route_entry(bgp, es, afi, safi, rn, - &attr, 1, &ri, - &route_changed); + ret = update_evpn_type4_route_entry(bgp, es, afi, safi, rn, &attr, 1, + &pi, &route_changed); if (ret != 0) { flog_err(EC_BGP_ES_INVALID, "%u ERROR: Failed to updated ES route ESI: %s VTEP %s", @@ -1395,8 +1395,8 @@ static int update_evpn_type4_route(struct bgp *bgp, ipaddr2str(&es->originator_ip, buf1, sizeof(buf1))); } - assert(ri); - attr_new = ri->attr; + assert(pi); + attr_new = pi->attr; /* Perform route selection; * this is just to set the flags correctly @@ -1411,14 +1411,12 @@ static int update_evpn_type4_route(struct bgp *bgp, * Prefix-level) similar to L3VPN routes. */ if (route_changed) { - struct bgp_info *global_ri; + struct bgp_path_info *global_pi; rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)p, &es->prd); - update_evpn_type4_route_entry(bgp, es, afi, safi, - rn, attr_new, - 1, &global_ri, - &route_changed); + update_evpn_type4_route_entry(bgp, es, afi, safi, rn, attr_new, + 1, &global_pi, &route_changed); /* Schedule for processing and unlock node. */ bgp_process(bgp, rn, afi, safi); @@ -1436,25 +1434,25 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, struct attr *attr, int *route_changed) { struct attr *attr_new = NULL; - struct bgp_info *ri = NULL; + struct bgp_path_info *pi = NULL; mpls_label_t label = MPLS_INVALID_LABEL; - struct bgp_info *local_ri = NULL; - struct bgp_info *tmp_ri = NULL; + struct bgp_path_info *local_pi = NULL; + struct bgp_path_info *tmp_pi = NULL; *route_changed = 0; /* locate the local route entry if any */ - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp_def->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp_def->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) + local_pi = tmp_pi; } /* - * create a new route entry if one doesnt exist. + * create a new route entry if one doesn't exist. * Otherwise see if route attr has changed */ - if (!local_ri) { + if (!local_pi) { /* route has changed as this is the first entry */ *route_changed = 1; @@ -1463,22 +1461,22 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, attr_new = bgp_attr_intern(attr); /* create the route info from attribute */ - ri = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, + pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp_def->peer_self, attr_new, rn); - SET_FLAG(ri->flags, BGP_INFO_VALID); + SET_FLAG(pi->flags, BGP_PATH_VALID); /* Type-5 routes advertise the L3-VNI */ - bgp_info_extra_get(ri); + bgp_path_info_extra_get(pi); vni2label(bgp_vrf->l3vni, &label); - memcpy(&ri->extra->label, &label, sizeof(label)); - ri->extra->num_labels = 1; + memcpy(&pi->extra->label, &label, sizeof(label)); + pi->extra->num_labels = 1; /* add the route entry to route node*/ - bgp_info_add(rn, ri); + bgp_path_info_add(rn, pi); } else { - tmp_ri = local_ri; - if (!attrhash_cmp(tmp_ri->attr, attr)) { + tmp_pi = local_pi; + if (!attrhash_cmp(tmp_pi->attr, attr)) { /* attribute changed */ *route_changed = 1; @@ -1486,16 +1484,17 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_def, /* The attribute has changed. */ /* Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(attr); - bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, tmp_pi, + BGP_PATH_ATTR_CHANGED); /* Restore route, if needed. */ - if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, tmp_ri); + if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, tmp_pi); /* Unintern existing, set to new. */ - bgp_attr_unintern(&tmp_ri->attr); - tmp_ri->attr = attr_new; - tmp_ri->uptime = bgp_clock(); + bgp_attr_unintern(&tmp_pi->attr); + tmp_pi->attr = attr_new; + tmp_pi->uptime = bgp_clock(); } } return 0; @@ -1562,11 +1561,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, afi_t afi, safi_t safi, struct bgp_node *rn, struct attr *attr, int add, - struct bgp_info **ri, uint8_t flags, + struct bgp_path_info **pi, uint8_t flags, uint32_t seq) { - struct bgp_info *tmp_ri; - struct bgp_info *local_ri; + struct bgp_path_info *tmp_pi; + struct bgp_path_info *local_pi; struct attr *attr_new; mpls_label_t label[BGP_MAX_LABELS]; uint32_t num_labels = 1; @@ -1574,31 +1573,31 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, uint8_t sticky = 0; struct prefix_evpn *evp; - *ri = NULL; + *pi = NULL; evp = (struct prefix_evpn *)&rn->p; memset(&label, 0, sizeof(label)); /* See if this is an update of an existing route, or a new add. */ - local_ri = NULL; - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) - local_ri = tmp_ri; + local_pi = NULL; + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) + local_pi = tmp_pi; } /* If route doesn't exist already, create a new one, if told to. * Otherwise act based on whether the attributes of the route have * changed or not. */ - if (!local_ri && !add) + if (!local_pi && !add) return 0; /* For non-GW MACs, update MAC mobility seq number, if needed. */ if (seq && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) add_mac_mobility_to_attr(seq, attr); - if (!local_ri) { + if (!local_pi) { /* Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(attr); @@ -1608,10 +1607,10 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, attr_new->sticky = sticky; /* Create new route with its attribute. */ - tmp_ri = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, + tmp_pi = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, rn); - SET_FLAG(tmp_ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(tmp_ri); + SET_FLAG(tmp_pi->flags, BGP_PATH_VALID); + bgp_path_info_extra_get(tmp_pi); /* The VNI goes into the 'label' field of the route */ vni2label(vpn->vni, &label[0]); @@ -1631,13 +1630,13 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, } } - memcpy(&tmp_ri->extra->label, label, sizeof(label)); - tmp_ri->extra->num_labels = num_labels; - bgp_info_add(rn, tmp_ri); + memcpy(&tmp_pi->extra->label, label, sizeof(label)); + tmp_pi->extra->num_labels = num_labels; + bgp_path_info_add(rn, tmp_pi); } else { - tmp_ri = local_ri; - if (attrhash_cmp(tmp_ri->attr, attr) - && !CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) + tmp_pi = local_pi; + if (attrhash_cmp(tmp_pi->attr, attr) + && !CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED)) route_change = 0; else { /* @@ -1656,13 +1655,14 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, num_labels++; } } - memcpy(&tmp_ri->extra->label, label, sizeof(label)); - tmp_ri->extra->num_labels = num_labels; + memcpy(&tmp_pi->extra->label, label, sizeof(label)); + tmp_pi->extra->num_labels = num_labels; /* The attribute has changed. */ /* Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(attr); - bgp_info_set_flag(rn, tmp_ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, tmp_pi, + BGP_PATH_ATTR_CHANGED); /* Extract MAC mobility sequence number, if any. */ attr_new->mm_seqnum = @@ -1670,18 +1670,18 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, attr_new->sticky = sticky; /* Restore route, if needed. */ - if (CHECK_FLAG(tmp_ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, tmp_ri); + if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, tmp_pi); /* Unintern existing, set to new. */ - bgp_attr_unintern(&tmp_ri->attr); - tmp_ri->attr = attr_new; - tmp_ri->uptime = bgp_clock(); + bgp_attr_unintern(&tmp_pi->attr); + tmp_pi->attr = attr_new; + tmp_pi->uptime = bgp_clock(); } } /* Return back the route entry. */ - *ri = tmp_ri; + *pi = tmp_pi; return route_change; } @@ -1697,7 +1697,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, struct attr attr; struct attr *attr_new; int add_l3_ecomm = 0; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; int route_change; @@ -1743,9 +1743,9 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, /* Create or update route entry. */ route_change = update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, - 1, &ri, flags, seq); - assert(ri); - attr_new = ri->attr; + 1, &pi, flags, seq); + assert(pi); + attr_new = pi->attr; /* Perform route selection; this is just to set the flags correctly * as local route in the VNI always wins. @@ -1759,12 +1759,12 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, * Prefix-level) similar to L3VPN routes. */ if (route_change) { - struct bgp_info *global_ri; + struct bgp_path_info *global_pi; rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)p, &vpn->prd); update_evpn_route_entry(bgp, vpn, afi, safi, rn, attr_new, 1, - &global_ri, flags, seq); + &global_pi, flags, seq); /* Schedule for processing and unlock node. */ bgp_process(bgp, rn, afi, safi); @@ -1781,27 +1781,26 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, * Delete EVPN route entry. * The entry can be in ESI/VNI table or the global table. */ -static void delete_evpn_route_entry(struct bgp *bgp, - afi_t afi, safi_t safi, +static void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi, struct bgp_node *rn, - struct bgp_info **ri) + struct bgp_path_info **pi) { - struct bgp_info *tmp_ri; + struct bgp_path_info *tmp_pi; - *ri = NULL; + *pi = NULL; /* Now, find matching route. */ - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) break; - *ri = tmp_ri; + *pi = tmp_pi; /* Mark route for delete. */ - if (tmp_ri) - bgp_info_delete(rn, tmp_ri); + if (tmp_pi) + bgp_path_info_delete(rn, tmp_pi); } @@ -1813,7 +1812,7 @@ static int delete_evpn_type4_route(struct bgp *bgp, { afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_node *rn = NULL; /* rn in esi table */ struct bgp_node *global_rn = NULL; /* rn in global table */ @@ -1833,13 +1832,12 @@ static int delete_evpn_type4_route(struct bgp *bgp, if (global_rn) { /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry(bgp, afi, safi, - global_rn, &ri); + delete_evpn_route_entry(bgp, afi, safi, global_rn, &pi); /* Schedule for processing - withdraws to peers happen from * this table. */ - if (ri) + if (pi) bgp_process(bgp, global_rn, afi, safi); bgp_unlock_node(global_rn); } @@ -1848,9 +1846,9 @@ static int delete_evpn_type4_route(struct bgp *bgp, * Delete route entry in the ESI route table. * This can just be removed. */ - delete_evpn_route_entry(bgp, afi, safi, rn, &ri); - if (ri) - bgp_info_reap(rn, ri); + delete_evpn_route_entry(bgp, afi, safi, rn, &pi); + if (pi) + bgp_path_info_reap(rn, pi); bgp_unlock_node(rn); return 0; } @@ -1861,7 +1859,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; struct bgp_node *rn = NULL; - struct bgp_info *ri = NULL; + struct bgp_path_info *pi = NULL; struct bgp *bgp_def = NULL; /* default bgp instance */ bgp_def = bgp_get_default(); @@ -1874,8 +1872,8 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp) if (!rn) return 0; - delete_evpn_route_entry(bgp_def, afi, safi, rn, &ri); - if (ri) + delete_evpn_route_entry(bgp_def, afi, safi, rn, &pi); + if (pi) bgp_process(bgp_def, rn, afi, safi); bgp_unlock_node(rn); return 0; @@ -1889,7 +1887,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, struct prefix_evpn *p) { struct bgp_node *rn, *global_rn; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -1910,21 +1908,21 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, (struct prefix *)p, &vpn->prd); if (global_rn) { /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry(bgp, afi, safi, global_rn, &ri); + delete_evpn_route_entry(bgp, afi, safi, global_rn, &pi); /* Schedule for processing - withdraws to peers happen from * this table. */ - if (ri) + if (pi) bgp_process(bgp, global_rn, afi, safi); bgp_unlock_node(global_rn); } /* Delete route entry in the VNI route table. This can just be removed. */ - delete_evpn_route_entry(bgp, afi, safi, rn, &ri); - if (ri) - bgp_info_reap(rn, ri); + delete_evpn_route_entry(bgp, afi, safi, rn, &pi); + if (pi) + bgp_path_info_reap(rn, pi); bgp_unlock_node(rn); return 0; @@ -1939,7 +1937,7 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) afi_t afi; safi_t safi; struct bgp_node *rn; - struct bgp_info *ri, *tmp_ri; + struct bgp_path_info *pi, *tmp_pi; struct attr attr; struct attr *attr_new; uint32_t seq; @@ -1955,20 +1953,20 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) rn = bgp_route_next(rn)) { struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; struct bgp_node *rd_rn; - struct bgp_info *global_ri; + struct bgp_path_info *global_pi; if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; /* Identify local route. */ - for (tmp_ri = rn->info; tmp_ri; tmp_ri = tmp_ri->next) { - if (tmp_ri->peer == bgp->peer_self - && tmp_ri->type == ZEBRA_ROUTE_BGP - && tmp_ri->sub_type == BGP_ROUTE_STATIC) + for (tmp_pi = rn->info; tmp_pi; tmp_pi = tmp_pi->next) { + if (tmp_pi->peer == bgp->peer_self + && tmp_pi->type == ZEBRA_ROUTE_BGP + && tmp_pi->sub_type == BGP_ROUTE_STATIC) break; } - if (!tmp_ri) + if (!tmp_pi) continue; /* @@ -2003,25 +2001,25 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) /* Set up extended community. */ build_evpn_route_extcomm(vpn, &attr, add_l3_ecomm); - seq = mac_mobility_seqnum(tmp_ri->attr); + seq = mac_mobility_seqnum(tmp_pi->attr); /* Update the route entry. */ - update_evpn_route_entry(bgp, vpn, afi, safi, rn, - &attr, 0, &ri, 0, seq); + update_evpn_route_entry(bgp, vpn, afi, safi, rn, &attr, 0, &pi, + 0, seq); /* Perform route selection; this is just to set the flags * correctly as local route in the VNI always wins. */ evpn_route_select_install(bgp, vpn, rn); - attr_new = ri->attr; + attr_new = pi->attr; /* Update route in global routing table. */ rd_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)evp, &vpn->prd); assert(rd_rn); update_evpn_route_entry(bgp, vpn, afi, safi, rd_rn, attr_new, 0, - &global_ri, 0, + &global_pi, 0, mac_mobility_seqnum(attr_new)); /* Schedule for processing and unlock node. */ @@ -2046,7 +2044,7 @@ static int delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) safi_t safi; struct bgp_node *rdrn, *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; afi = AFI_L2VPN; safi = SAFI_EVPN; @@ -2060,8 +2058,8 @@ static int delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - delete_evpn_route_entry(bgp, afi, safi, rn, &ri); - if (ri) + delete_evpn_route_entry(bgp, afi, safi, rn, &pi); + if (pi) bgp_process(bgp, rn, afi, safi); } } @@ -2082,7 +2080,7 @@ static int delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) afi_t afi; safi_t safi; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; afi = AFI_L2VPN; safi = SAFI_EVPN; @@ -2101,11 +2099,11 @@ static int delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - delete_evpn_route_entry(bgp, afi, safi, rn, &ri); + delete_evpn_route_entry(bgp, afi, safi, rn, &pi); /* Route entry in local table gets deleted immediately. */ - if (ri) - bgp_info_reap(rn, ri); + if (pi) + bgp_path_info_reap(rn, pi); } return 0; @@ -2117,15 +2115,15 @@ static int delete_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn) static int delete_all_es_routes(struct bgp *bgp, struct evpnes *es) { struct bgp_node *rn; - struct bgp_info *ri, *nextri; + struct bgp_path_info *pi, *nextpi; /* Walk this ES's route table and delete all routes. */ for (rn = bgp_table_top(es->route_table); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); - ri = nextri) { - bgp_info_delete(rn, ri); - bgp_info_reap(rn, ri); + for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); + pi = nextpi) { + bgp_path_info_delete(rn, pi); + bgp_path_info_reap(rn, pi); } } @@ -2138,15 +2136,15 @@ static int delete_all_es_routes(struct bgp *bgp, struct evpnes *es) static int delete_all_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) { struct bgp_node *rn; - struct bgp_info *ri, *nextri; + struct bgp_path_info *pi, *nextpi; /* Walk this VNI's route table and delete all routes. */ for (rn = bgp_table_top(vpn->route_table); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); - ri = nextri) { - bgp_info_delete(rn, ri); - bgp_info_reap(rn, ri); + for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); + pi = nextpi) { + bgp_path_info_delete(rn, pi); + bgp_path_info_reap(rn, pi); } } @@ -2166,11 +2164,15 @@ static int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) /* Update and advertise the type-3 route (only one) followed by the * locally learnt type-2 routes (MACIP) - for this VNI. + * + * RT-3 only if doing head-end replication */ - build_evpn_type3_prefix(&p, vpn->originator_ip); - ret = update_evpn_route(bgp, vpn, &p, 0, 0); - if (ret) - return ret; + if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) { + build_evpn_type3_prefix(&p, vpn->originator_ip); + ret = update_evpn_route(bgp, vpn, &p, 0, 0); + if (ret) + return ret; + } return update_all_type2_routes(bgp, vpn); } @@ -2261,14 +2263,13 @@ static int handle_tunnel_ip_change(struct bgp *bgp, struct bgpevpn *vpn, } /* Install EVPN route entry in ES */ -static int install_evpn_route_entry_in_es(struct bgp *bgp, - struct evpnes *es, +static int install_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, struct prefix_evpn *p, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { int ret = 0; struct bgp_node *rn = NULL; - struct bgp_info *ri = NULL; + struct bgp_path_info *pi = NULL; struct attr *attr_new = NULL; /* Create (or fetch) route within the VNI. @@ -2277,44 +2278,44 @@ static int install_evpn_route_entry_in_es(struct bgp *bgp, rn = bgp_node_get(es->route_table, (struct prefix *)p); /* Check if route entry is already present. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra && - (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) { + if (!pi) { /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(parent_pi->attr); /* Create new route with its attribute. */ - ri = info_make(parent_ri->type, BGP_ROUTE_IMPORTED, 0, - parent_ri->peer, attr_new, rn); - SET_FLAG(ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(ri); - ri->extra->parent = parent_ri; - bgp_info_add(rn, ri); + pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0, + parent_pi->peer, attr_new, rn); + SET_FLAG(pi->flags, BGP_PATH_VALID); + bgp_path_info_extra_get(pi); + pi->extra->parent = parent_pi; + bgp_path_info_add(rn, pi); } else { - if (attrhash_cmp(ri->attr, parent_ri->attr) - && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(pi->attr, parent_pi->attr) + && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { bgp_unlock_node(rn); return 0; } /* The attribute has changed. */ /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(parent_pi->attr); /* Restore route, if needed. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, pi); /* Mark if nexthop has changed. */ - if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) - SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); + if (!IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop)) + SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED); /* Unintern existing, set to new. */ - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock(); + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; + pi->uptime = bgp_clock(); } /* Perform route selection and update zebra, if required. */ @@ -2327,10 +2328,10 @@ static int install_evpn_route_entry_in_es(struct bgp *bgp, */ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, struct prefix_evpn *evp, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct attr attr; struct attr *attr_new; int ret = 0; @@ -2371,38 +2372,38 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * address for the rest of the code to flow through. In the case of IPv4, * make sure to set the flag for next hop attribute. */ - bgp_attr_dup(&attr, parent_ri->attr); + bgp_attr_dup(&attr, parent_pi->attr); if (afi == AFI_IP6) evpn_convert_nexthop_to_ipv6(&attr); else attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); /* Check if route entry is already present. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra - && (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) { + if (!pi) { /* Add (or update) attribute to hash. */ attr_new = bgp_attr_intern(&attr); /* Create new route with its attribute. */ - ri = info_make(parent_ri->type, BGP_ROUTE_IMPORTED, 0, - parent_ri->peer, attr_new, rn); - SET_FLAG(ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(ri); - ri->extra->parent = bgp_info_lock(parent_ri); - bgp_lock_node((struct bgp_node *)parent_ri->net); - if (parent_ri->extra) { - memcpy(&ri->extra->label, &parent_ri->extra->label, - sizeof(ri->extra->label)); - ri->extra->num_labels = parent_ri->extra->num_labels; + pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0, + parent_pi->peer, attr_new, rn); + SET_FLAG(pi->flags, BGP_PATH_VALID); + bgp_path_info_extra_get(pi); + pi->extra->parent = bgp_path_info_lock(parent_pi); + bgp_lock_node((struct bgp_node *)parent_pi->net); + if (parent_pi->extra) { + memcpy(&pi->extra->label, &parent_pi->extra->label, + sizeof(pi->extra->label)); + pi->extra->num_labels = parent_pi->extra->num_labels; } - bgp_info_add(rn, ri); + bgp_path_info_add(rn, pi); } else { - if (attrhash_cmp(ri->attr, &attr) - && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(pi->attr, &attr) + && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { bgp_unlock_node(rn); return 0; } @@ -2411,24 +2412,24 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, attr_new = bgp_attr_intern(&attr); /* Restore route, if needed. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, pi); /* Mark if nexthop has changed. */ - if ((afi == AFI_IP && - !IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) || - (afi == AFI_IP6 && - !IPV6_ADDR_SAME(&ri->attr->mp_nexthop_global, - &attr_new->mp_nexthop_global))) - SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); + if ((afi == AFI_IP + && !IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop)) + || (afi == AFI_IP6 + && !IPV6_ADDR_SAME(&pi->attr->mp_nexthop_global, + &attr_new->mp_nexthop_global))) + SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED); /* Unintern existing, set to new. */ - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock(); + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; + pi->uptime = bgp_clock(); } - bgp_aggregate_increment(bgp_vrf, &rn->p, ri, afi, safi); + bgp_aggregate_increment(bgp_vrf, &rn->p, pi, afi, safi); /* Perform route selection and update zebra, if required. */ bgp_process(bgp_vrf, rn, afi, safi); @@ -2441,10 +2442,10 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, */ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, struct prefix_evpn *p, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct attr *attr_new; int ret; @@ -2453,50 +2454,50 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, rn = bgp_node_get(vpn->route_table, (struct prefix *)p); /* Check if route entry is already present. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra - && (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) { + if (!pi) { /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(parent_pi->attr); /* Create new route with its attribute. */ - ri = info_make(parent_ri->type, BGP_ROUTE_IMPORTED, 0, - parent_ri->peer, attr_new, rn); - SET_FLAG(ri->flags, BGP_INFO_VALID); - bgp_info_extra_get(ri); - ri->extra->parent = bgp_info_lock(parent_ri); - bgp_lock_node((struct bgp_node *)parent_ri->net); - if (parent_ri->extra) { - memcpy(&ri->extra->label, &parent_ri->extra->label, - sizeof(ri->extra->label)); - ri->extra->num_labels = parent_ri->extra->num_labels; + pi = info_make(parent_pi->type, BGP_ROUTE_IMPORTED, 0, + parent_pi->peer, attr_new, rn); + SET_FLAG(pi->flags, BGP_PATH_VALID); + bgp_path_info_extra_get(pi); + pi->extra->parent = bgp_path_info_lock(parent_pi); + bgp_lock_node((struct bgp_node *)parent_pi->net); + if (parent_pi->extra) { + memcpy(&pi->extra->label, &parent_pi->extra->label, + sizeof(pi->extra->label)); + pi->extra->num_labels = parent_pi->extra->num_labels; } - bgp_info_add(rn, ri); + bgp_path_info_add(rn, pi); } else { - if (attrhash_cmp(ri->attr, parent_ri->attr) - && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(pi->attr, parent_pi->attr) + && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { bgp_unlock_node(rn); return 0; } /* The attribute has changed. */ /* Add (or update) attribute to hash. */ - attr_new = bgp_attr_intern(parent_ri->attr); + attr_new = bgp_attr_intern(parent_pi->attr); /* Restore route, if needed. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, pi); /* Mark if nexthop has changed. */ - if (!IPV4_ADDR_SAME(&ri->attr->nexthop, &attr_new->nexthop)) - SET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); + if (!IPV4_ADDR_SAME(&pi->attr->nexthop, &attr_new->nexthop)) + SET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED); /* Unintern existing, set to new. */ - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock(); + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; + pi->uptime = bgp_clock(); } /* Perform route selection and update zebra, if required. */ @@ -2506,14 +2507,13 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, } /* Uninstall EVPN route entry from ES route table */ -static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, - struct evpnes *es, +static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, struct evpnes *es, struct prefix_evpn *p, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { int ret; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; if (!es->route_table) return 0; @@ -2526,16 +2526,16 @@ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, return 0; /* Find matching route entry. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra && - (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) + if (!pi) return 0; /* Mark entry for deletion */ - bgp_info_delete(rn, ri); + bgp_path_info_delete(rn, pi); /* Perform route selection and update zebra, if required. */ ret = evpn_es_route_select_install(bgp, es, rn); @@ -2552,10 +2552,10 @@ static int uninstall_evpn_route_entry_in_es(struct bgp *bgp, */ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, struct prefix_evpn *evp, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; int ret = 0; struct prefix p; struct prefix *pp = &p; @@ -2591,18 +2591,18 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, return 0; /* Find matching route entry. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra - && (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) + if (!pi) return 0; - bgp_aggregate_decrement(bgp_vrf, &rn->p, ri, afi, safi); + bgp_aggregate_decrement(bgp_vrf, &rn->p, pi, afi, safi); /* Mark entry for deletion */ - bgp_info_delete(rn, ri); + bgp_path_info_delete(rn, pi); /* Perform route selection and update zebra, if required. */ bgp_process(bgp_vrf, rn, afi, safi); @@ -2619,10 +2619,10 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, */ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, struct prefix_evpn *p, - struct bgp_info *parent_ri) + struct bgp_path_info *parent_pi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; int ret; /* Locate route within the VNI. */ @@ -2632,16 +2632,16 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, return 0; /* Find matching route entry. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->extra - && (struct bgp_info *)ri->extra->parent == parent_ri) + for (pi = rn->info; pi; pi = pi->next) + if (pi->extra + && (struct bgp_path_info *)pi->extra->parent == parent_pi) break; - if (!ri) + if (!pi) return 0; /* Mark entry for deletion */ - bgp_info_delete(rn, ri); + bgp_path_info_delete(rn, pi); /* Perform route selection and update zebra, if required. */ ret = evpn_route_select_install(bgp, vpn, rn); @@ -2672,9 +2672,10 @@ static int is_prefix_matching_for_es(struct prefix_evpn *p, * Given a route entry and a VRF, see if this route entry should be * imported into the VRF i.e., RTs match. */ -static int is_route_matching_for_vrf(struct bgp *bgp_vrf, struct bgp_info *ri) +static int is_route_matching_for_vrf(struct bgp *bgp_vrf, + struct bgp_path_info *pi) { - struct attr *attr = ri->attr; + struct attr *attr = pi->attr; struct ecommunity *ecom; int i; @@ -2739,9 +2740,9 @@ static int is_route_matching_for_vrf(struct bgp *bgp_vrf, struct bgp_info *ri) * imported into the VNI i.e., RTs match. */ static int is_route_matching_for_vni(struct bgp *bgp, struct bgpevpn *vpn, - struct bgp_info *ri) + struct bgp_path_info *pi) { - struct attr *attr = ri->attr; + struct attr *attr = pi->attr; struct ecommunity *ecom; int i; @@ -2812,7 +2813,7 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, char buf1[ESI_STR_LEN]; struct bgp_node *rd_rn, *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; afi = AFI_L2VPN; safi = SAFI_EVPN; @@ -2831,14 +2832,14 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p; - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { /* * Consider "valid" remote routes applicable for * this ES. */ - if (!(CHECK_FLAG(ri->flags, BGP_INFO_VALID) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL)) + if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_NORMAL)) continue; if (!is_prefix_matching_for_es(evp, es)) @@ -2846,10 +2847,10 @@ static int install_uninstall_routes_for_es(struct bgp *bgp, if (install) ret = install_evpn_route_entry_in_es( - bgp, es, evp, ri); + bgp, es, evp, pi); else ret = uninstall_evpn_route_entry_in_es( - bgp, es, evp, ri); + bgp, es, evp, pi); if (ret) { flog_err( @@ -2879,7 +2880,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) safi_t safi; struct bgp_node *rd_rn, *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; int ret; char buf[PREFIX_STRLEN]; struct bgp *bgp_def = NULL; @@ -2914,22 +2915,22 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install) || is_evpn_prefix_ipaddr_v6(evp))) continue; - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { /* Consider "valid" remote routes applicable for * this VRF. */ - if (!(CHECK_FLAG(ri->flags, BGP_INFO_VALID) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL)) + if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_NORMAL)) continue; - if (is_route_matching_for_vrf(bgp_vrf, ri)) { + if (is_route_matching_for_vrf(bgp_vrf, pi)) { if (install) ret = install_evpn_route_entry_in_vrf( - bgp_vrf, evp, ri); + bgp_vrf, evp, pi); else ret = uninstall_evpn_route_entry_in_vrf( - bgp_vrf, evp, ri); + bgp_vrf, evp, pi); if (ret) { flog_err( @@ -2964,7 +2965,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, safi_t safi; struct bgp_node *rd_rn, *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; int ret; afi = AFI_L2VPN; @@ -2989,21 +2990,21 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp, if (evp->prefix.route_type != rtype) continue; - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { /* Consider "valid" remote routes applicable for * this VNI. */ - if (!(CHECK_FLAG(ri->flags, BGP_INFO_VALID) - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL)) + if (!(CHECK_FLAG(pi->flags, BGP_PATH_VALID) + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_NORMAL)) continue; - if (is_route_matching_for_vni(bgp, vpn, ri)) { + if (is_route_matching_for_vni(bgp, vpn, pi)) { if (install) ret = install_evpn_route_entry( - bgp, vpn, evp, ri); + bgp, vpn, evp, pi); else ret = uninstall_evpn_route_entry( - bgp, vpn, evp, ri); + bgp, vpn, evp, pi); if (ret) { flog_err( @@ -3097,16 +3098,15 @@ static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn) static int install_uninstall_route_in_es(struct bgp *bgp, struct evpnes *es, afi_t afi, safi_t safi, struct prefix_evpn *evp, - struct bgp_info *ri, - int install) + struct bgp_path_info *pi, int install) { int ret = 0; char buf[ESI_STR_LEN]; if (install) - ret = install_evpn_route_entry_in_es(bgp, es, evp, ri); + ret = install_evpn_route_entry_in_es(bgp, es, evp, pi); else - ret = uninstall_evpn_route_entry_in_es(bgp, es, evp, ri); + ret = uninstall_evpn_route_entry_in_es(bgp, es, evp, pi); if (ret) { flog_err( @@ -3124,7 +3124,7 @@ static int install_uninstall_route_in_es(struct bgp *bgp, struct evpnes *es, */ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, safi_t safi, struct prefix_evpn *evp, - struct bgp_info *ri, + struct bgp_path_info *pi, struct list *vrfs, int install) { char buf[PREFIX2STR_BUFFER]; @@ -3146,10 +3146,10 @@ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, int ret; if (install) - ret = install_evpn_route_entry_in_vrf(bgp_vrf, evp, ri); + ret = install_evpn_route_entry_in_vrf(bgp_vrf, evp, pi); else ret = uninstall_evpn_route_entry_in_vrf(bgp_vrf, evp, - ri); + pi); if (ret) { flog_err(EC_BGP_EVPN_FAIL, @@ -3170,7 +3170,7 @@ static int install_uninstall_route_in_vrfs(struct bgp *bgp_def, afi_t afi, */ static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix_evpn *evp, - struct bgp_info *ri, + struct bgp_path_info *pi, struct list *vnis, int install) { struct bgpevpn *vpn; @@ -3183,9 +3183,9 @@ static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, continue; if (install) - ret = install_evpn_route_entry(bgp, vpn, evp, ri); + ret = install_evpn_route_entry(bgp, vpn, evp, pi); else - ret = uninstall_evpn_route_entry(bgp, vpn, evp, ri); + ret = uninstall_evpn_route_entry(bgp, vpn, evp, pi); if (ret) { flog_err(EC_BGP_EVPN_FAIL, @@ -3206,11 +3206,11 @@ static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi, * Install or uninstall route for appropriate VNIs/ESIs. */ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri, - int import) + struct prefix *p, + struct bgp_path_info *pi, int import) { struct prefix_evpn *evp = (struct prefix_evpn *)p; - struct attr *attr = ri->attr; + struct attr *attr = pi->attr; struct ecommunity *ecom; int i; @@ -3262,17 +3262,15 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, irt = lookup_import_rt(bgp, eval); if (irt) - install_uninstall_route_in_vnis(bgp, afi, safi, - evp, ri, - irt->vnis, - import); + install_uninstall_route_in_vnis( + bgp, afi, safi, evp, pi, irt->vnis, + import); vrf_irt = lookup_vrf_import_rt(eval); if (vrf_irt) - install_uninstall_route_in_vrfs(bgp, afi, safi, - evp, ri, - vrf_irt->vrfs, - import); + install_uninstall_route_in_vrfs( + bgp, afi, safi, evp, pi, vrf_irt->vrfs, + import); /* Also check for non-exact match. * In this, we mask out the AS and @@ -3292,15 +3290,13 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, } if (irt) - install_uninstall_route_in_vnis(bgp, afi, safi, - evp, ri, - irt->vnis, - import); + install_uninstall_route_in_vnis( + bgp, afi, safi, evp, pi, irt->vnis, + import); if (vrf_irt) - install_uninstall_route_in_vrfs(bgp, afi, safi, - evp, ri, - vrf_irt->vrfs, - import); + install_uninstall_route_in_vrfs( + bgp, afi, safi, evp, pi, vrf_irt->vrfs, + import); } /* es route is imported into the es table */ @@ -3311,9 +3307,8 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, */ es = bgp_evpn_lookup_es(bgp, &evp->prefix.es_addr.esi); if (es && is_es_local(es)) - install_uninstall_route_in_es(bgp, es, - afi, safi, - evp, ri, import); + install_uninstall_route_in_es( + bgp, es, afi, safi, evp, pi, import); } } @@ -3393,7 +3388,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) { struct prefix_evpn p; struct bgp_node *rn, *global_rn; - struct bgp_info *ri, *global_ri; + struct bgp_path_info *pi, *global_pi; struct attr *attr; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -3401,27 +3396,32 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) /* Locate type-3 route for VNI in the per-VNI table and use its * attributes to create and advertise the type-3 route for this VNI * in the global table. + * + * RT-3 only if doing head-end replication */ - build_evpn_type3_prefix(&p, vpn->originator_ip); - rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); - if (!rn) /* unexpected */ - return 0; - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - break; - if (!ri) /* unexpected */ - return 0; - attr = ri->attr; + if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) { + build_evpn_type3_prefix(&p, vpn->originator_ip); + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (!rn) /* unexpected */ + return 0; + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && + pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) + break; + if (!pi) /* unexpected */ + return 0; + attr = pi->attr; - global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, - (struct prefix *)&p, &vpn->prd); - update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, &ri, - 0, mac_mobility_seqnum(attr)); + global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, + (struct prefix *)&p, &vpn->prd); + update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, + 1, &pi, 0, mac_mobility_seqnum(attr)); - /* Schedule for processing and unlock node. */ - bgp_process(bgp, global_rn, afi, safi); - bgp_unlock_node(global_rn); + /* Schedule for processing and unlock node. */ + bgp_process(bgp, global_rn, afi, safi); + bgp_unlock_node(global_rn); + } /* Now, walk this VNI's route table and use the route and its attribute * to create and schedule route in global table. @@ -3434,23 +3434,23 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE) continue; - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) break; - if (!ri) + if (!pi) continue; /* Create route in global routing table using this route entry's * attribute. */ - attr = ri->attr; + attr = pi->attr; global_rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, (struct prefix *)evp, &vpn->prd); assert(global_rn); update_evpn_route_entry(bgp, vpn, afi, safi, global_rn, attr, 1, - &global_ri, 0, + &global_pi, 0, mac_mobility_seqnum(attr)); /* Schedule for processing and unlock node. */ @@ -3470,7 +3470,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) int ret; struct prefix_evpn p; struct bgp_node *global_rn; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; @@ -3487,12 +3487,12 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn) (struct prefix *)&p, &vpn->prd); if (global_rn) { /* Delete route entry in the global EVPN table. */ - delete_evpn_route_entry(bgp, afi, safi, global_rn, &ri); + delete_evpn_route_entry(bgp, afi, safi, global_rn, &pi); /* Schedule for processing - withdraws to peers happen from * this table. */ - if (ri) + if (pi) bgp_process(bgp, global_rn, afi, safi); bgp_unlock_node(global_rn); } @@ -3535,6 +3535,42 @@ static void withdraw_router_id_vni(struct hash_backet *backet, struct bgp *bgp) delete_withdraw_vni_routes(bgp, vpn); } +/* + * Create RT-3 for a VNI and schedule for processing and advertisement. + * This is invoked upon flooding mode changing to head-end replication. + */ +static void create_advertise_type3(struct hash_backet *backet, void *data) +{ + struct bgpevpn *vpn = backet->data; + struct bgp *bgp = data; + struct prefix_evpn p; + + if (!vpn || !is_vni_live(vpn)) + return; + + build_evpn_type3_prefix(&p, vpn->originator_ip); + if (update_evpn_route(bgp, vpn, &p, 0, 0)) + flog_err(EC_BGP_EVPN_ROUTE_CREATE, + "Type3 route creation failure for VNI %u", vpn->vni); +} + +/* + * Delete RT-3 for a VNI and schedule for processing and withdrawal. + * This is invoked upon flooding mode changing to drop BUM packets. + */ +static void delete_withdraw_type3(struct hash_backet *backet, void *data) +{ + struct bgpevpn *vpn = backet->data; + struct bgp *bgp = data; + struct prefix_evpn p; + + if (!vpn || !is_vni_live(vpn)) + return; + + build_evpn_type3_prefix(&p, vpn->originator_ip); + delete_evpn_route(bgp, vpn, &p); +} + /* * Process received EVPN type-2 route (advertise or withdraw). */ @@ -4090,15 +4126,15 @@ void bgp_evpn_withdraw_type5_routes(struct bgp *bgp_vrf, afi_t afi, safi_t safi) { struct bgp_table *table = NULL; struct bgp_node *rn = NULL; - struct bgp_info *ri; + struct bgp_path_info *pi; table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { /* Only care about "selected" routes - non-imported. */ /* TODO: Support for AddPath for EVPN. */ - for (ri = rn->info; ri; ri = ri->next) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) - && (!ri->extra || !ri->extra->parent)) { + for (pi = rn->info; pi; pi = pi->next) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) + && (!pi->extra || !pi->extra->parent)) { bgp_evpn_withdraw_type5_route(bgp_vrf, &rn->p, afi, safi); break; @@ -4138,7 +4174,7 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, { struct bgp_table *table = NULL; struct bgp_node *rn = NULL; - struct bgp_info *ri; + struct bgp_path_info *pi; table = bgp_vrf->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { @@ -4146,9 +4182,9 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, * attribute. Also, we only consider "non-imported" routes. * TODO: Support for AddPath for EVPN. */ - for (ri = rn->info; ri; ri = ri->next) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) - && (!ri->extra || !ri->extra->parent)) { + for (pi = rn->info; pi; pi = pi->next) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) + && (!pi->extra || !pi->extra->parent)) { /* apply the route-map */ if (bgp_vrf->adv_cmd_rmap[afi][safi].map) { @@ -4157,12 +4193,12 @@ void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi, ret = route_map_apply( bgp_vrf->adv_cmd_rmap[afi][safi] .map, - &rn->p, RMAP_BGP, ri); + &rn->p, RMAP_BGP, pi); if (ret == RMAP_DENYMATCH) continue; } bgp_evpn_advertise_type5_route( - bgp_vrf, &rn->p, ri->attr, afi, safi); + bgp_vrf, &rn->p, pi->attr, afi, safi); break; } } @@ -5033,7 +5069,7 @@ struct evpnes *bgp_evpn_es_new(struct bgp *bgp, /* Initialise the VTEP list */ es->vtep_list = list_new(); - es->vtep_list->cmp = (int (*)(void *, void *))evpn_vtep_ip_cmp; + es->vtep_list->cmp = evpn_vtep_ip_cmp; /* auto derive RD for this es */ bf_assign_index(bm->rd_idspace, es->rd_id); @@ -5074,18 +5110,18 @@ void bgp_evpn_es_free(struct bgp *bgp, struct evpnes *es) * Import evpn route from global table to VNI/VRF/ESI. */ int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri) + struct prefix *p, struct bgp_path_info *pi) { - return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 1); + return install_uninstall_evpn_route(bgp, afi, safi, p, pi, 1); } /* * Unimport evpn route from VNI/VRF/ESI. */ int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri) + struct prefix *p, struct bgp_path_info *pi) { - return install_uninstall_evpn_route(bgp, afi, safi, p, ri, 0); + return install_uninstall_evpn_route(bgp, afi, safi, p, pi, 0); } /* filter routes which have martian next hops */ @@ -5095,7 +5131,7 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) safi_t safi; struct bgp_node *rd_rn, *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; afi = AFI_L2VPN; safi = SAFI_EVPN; @@ -5114,23 +5150,23 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { /* Consider "valid" remote routes applicable for * this VNI. */ - if (!(ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_NORMAL)) + if (!(pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_NORMAL)) continue; - if (bgp_nexthop_self(bgp, ri->attr->nexthop)) { + if (bgp_nexthop_self(bgp, pi->attr->nexthop)) { char attr_str[BUFSIZ]; char pbuf[PREFIX_STRLEN]; - bgp_dump_attr(ri->attr, attr_str, + bgp_dump_attr(pi->attr, attr_str, BUFSIZ); - if (bgp_debug_update(ri->peer, &rn->p, + if (bgp_debug_update(pi->peer, &rn->p, NULL, 1)) zlog_debug( "%u: prefix %s with attr %s - DENIED due to martian or self nexthop", @@ -5141,9 +5177,9 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) attr_str); bgp_evpn_unimport_route(bgp, afi, safi, - &rn->p, ri); + &rn->p, pi); - bgp_rib_remove(rn, ri, ri->peer, afi, + bgp_rib_remove(rn, pi, pi->peer, afi, safi); } } @@ -5252,7 +5288,7 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id, struct ethaddr *rmac, } as = bgp_def->as; - /* if the BGP vrf instance doesnt exist - create one */ + /* if the BGP vrf instance doesn't exist - create one */ bgp_vrf = bgp_lookup_by_name(vrf_id_to_name(vrf_id)); if (!bgp_vrf) { @@ -5349,7 +5385,7 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id) } /* Remove remote routes from BGT VRF even if BGP_VRF_AUTO is configured, - * bgp_delete would not remove/decrement bgp_info of the ip_prefix + * bgp_delete would not remove/decrement bgp_path_info of the ip_prefix * routes. This will uninstalling the routes from zebra and decremnt the * bgp info count. */ @@ -5494,13 +5530,19 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni, /* filter routes as nexthop database has changed */ bgp_filter_evpn_routes_upon_martian_nh_change(bgp); - /* Create EVPN type-3 route and schedule for processing. */ - build_evpn_type3_prefix(&p, vpn->originator_ip); - if (update_evpn_route(bgp, vpn, &p, 0, 0)) { - flog_err(EC_BGP_EVPN_ROUTE_CREATE, - "%u: Type3 route creation failure for VNI %u", - bgp->vrf_id, vni); - return -1; + /* + * Create EVPN type-3 route and schedule for processing. + * + * RT-3 only if doing head-end replication + */ + if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) { + build_evpn_type3_prefix(&p, vpn->originator_ip); + if (update_evpn_route(bgp, vpn, &p, 0, 0)) { + flog_err(EC_BGP_EVPN_ROUTE_CREATE, + "%u: Type3 route creation failure for VNI %u", + bgp->vrf_id, vni); + return -1; + } } /* If we have learnt and retained remote routes (VTEPs, MACs) for this @@ -5598,6 +5640,26 @@ int bgp_evpn_local_es_add(struct bgp *bgp, return 0; } +/* + * Handle change in setting for BUM handling. The supported values + * are head-end replication and dropping all BUM packets. Any change + * should be registered with zebra. Also, if doing head-end replication, + * need to advertise local VNIs as EVPN RT-3 wheras, if BUM packets are + * to be dropped, the RT-3s must be withdrawn. + */ +void bgp_evpn_flood_control_change(struct bgp *bgp) +{ + zlog_info("L2VPN EVPN BUM handling is %s", + bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL ? + "Flooding" : "Flooding Disabled"); + + bgp_zebra_vxlan_flood_control(bgp, bgp->vxlan_flood_ctrl); + if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL) + hash_iterate(bgp->vnihash, create_advertise_type3, bgp); + else if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED) + hash_iterate(bgp->vnihash, delete_withdraw_type3, bgp); +} + /* * Cleanup EVPN information on disable - Need to delete and withdraw * EVPN routes from peers. @@ -5664,7 +5726,10 @@ void bgp_evpn_init(struct bgp *bgp) (int (*)(void *, void *))evpn_route_target_cmp; bgp->vrf_export_rtl->del = evpn_xxport_delete_ecomm; bgp->l2vnis = list_new(); - bgp->l2vnis->cmp = (int (*)(void *, void *))vni_hash_cmp; + bgp->l2vnis->cmp = vni_list_cmp; + + /* Default BUM handling is to do head-end replication. */ + bgp->vxlan_flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL; } void bgp_evpn_vrf_delete(struct bgp *bgp_vrf) diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index b002be3d3d..8728fdcab7 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -76,9 +76,9 @@ static inline int advertise_type5_routes(struct bgp *bgp_vrf, } /* Flag if the route's parent is a EVPN route. */ -static inline int is_route_parent_evpn(struct bgp_info *ri) +static inline int is_route_parent_evpn(struct bgp_path_info *ri) { - struct bgp_info *parent_ri; + struct bgp_path_info *parent_ri; struct bgp_table *table; struct bgp_node *rn; @@ -89,7 +89,7 @@ static inline int is_route_parent_evpn(struct bgp_info *ri) return 0; /* See if the parent is of family L2VPN/EVPN */ - parent_ri = (struct bgp_info *)ri->extra->parent; + parent_ri = (struct bgp_path_info *)ri->extra->parent; rn = parent_ri->net; if (!rn) return 0; @@ -124,9 +124,9 @@ extern void bgp_evpn_encode_prefix(struct stream *s, struct prefix *p, extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr, struct bgp_nlri *packet, int withdraw); extern int bgp_evpn_import_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri); + struct prefix *p, struct bgp_path_info *ri); extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct prefix *p, struct bgp_info *ri); + struct prefix *p, struct bgp_path_info *ri); extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp); extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, struct ipaddr *ip); @@ -145,6 +145,7 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, struct ipaddr *originator_ip); extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi, struct ipaddr *originator_ip); +extern void bgp_evpn_flood_control_change(struct bgp *bgp); extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp); extern void bgp_evpn_cleanup(struct bgp *bgp); extern void bgp_evpn_init(struct bgp *bgp); diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 5a1e8edac4..29f9f64cca 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -536,7 +536,7 @@ static void show_esi_routes(struct bgp *bgp, { int header = 1; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; uint32_t prefix_cnt, path_cnt; uint64_t tbl_ver; @@ -573,13 +573,13 @@ static void show_esi_routes(struct bgp *bgp, /* For EVPN, the prefix is displayed for each path (to fit in * with code that already exists). */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (json) json_path = json_object_new_array(); - route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path); + route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path); if (json) json_object_array_add(json_paths, json_path); @@ -616,7 +616,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, json_object *json) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_table *table; int header = 1; uint64_t tbl_ver; @@ -660,18 +660,18 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type, /* For EVPN, the prefix is displayed for each path (to fit in * with code that already exists). */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (vtep_ip.s_addr && !IPV4_ADDR_SAME(&(vtep_ip), - &(ri->attr->nexthop))) + &(pi->attr->nexthop))) continue; if (json) json_path = json_object_new_array(); - route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path); + route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path); if (json) json_object_array_add(json_paths, json_path); @@ -990,7 +990,7 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, struct bgp_table *table; struct bgp_node *rn; struct bgp_node *rm; - struct bgp_info *ri; + struct bgp_path_info *pi; int rd_header; int header = 1; @@ -1046,14 +1046,14 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, tbl_ver = table->version; for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) - for (ri = rm->info; ri; ri = ri->next) { + for (pi = rm->info; pi; pi = pi->next) { total_count++; if (type == bgp_show_type_neighbor) { union sockunion *su = output_arg; - if (ri->peer->su_remote == NULL + if (pi->peer->su_remote == NULL || !sockunion_same( - ri->peer->su_remote, su)) + pi->peer->su_remote, su)) continue; } if (header == 0) { @@ -1162,14 +1162,14 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd, else json_array = NULL; if (option == SHOW_DISPLAY_TAGS) - route_vty_out_tag(vty, &rm->p, ri, 0, + route_vty_out_tag(vty, &rm->p, pi, 0, SAFI_EVPN, json_array); else if (option == SHOW_DISPLAY_OVERLAY) - route_vty_out_overlay(vty, &rm->p, ri, + route_vty_out_overlay(vty, &rm->p, pi, 0, json_array); else - route_vty_out(vty, &rm->p, ri, 0, + route_vty_out(vty, &rm->p, pi, 0, SAFI_EVPN, json_array); output_count++; } @@ -2017,7 +2017,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, struct bgpevpn *vpn; struct prefix_evpn p; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; uint32_t path_cnt = 0; afi_t afi; safi_t safi; @@ -2049,13 +2049,13 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp, route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json); /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, + route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, json_path); if (json) @@ -2086,7 +2086,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, struct bgpevpn *vpn; struct prefix_evpn p; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; uint32_t path_cnt = 0; afi_t afi; safi_t safi; @@ -2119,13 +2119,13 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp, route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json); /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, + route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, json_path); if (json) @@ -2196,7 +2196,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, { struct prefix_evpn p; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi; safi_t safi; uint32_t path_cnt = 0; @@ -2226,13 +2226,13 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp, json_paths = json_object_new_array(); /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, + route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, json_path); if (json) @@ -2262,7 +2262,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, struct bgp_node *rd_rn; struct bgp_table *table; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; int rd_header = 1; afi_t afi; safi_t safi; @@ -2330,13 +2330,13 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp, json_paths = json_object_new_array(); /* Display each path for this prefix. */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; if (json) json_path = json_object_new_array(); - route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi, + route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi, json_path); if (json) @@ -2383,7 +2383,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, struct bgp_node *rd_rn; struct bgp_table *table; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; int header = 1; int rd_header; afi_t afi; @@ -2467,7 +2467,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, * fit in * with code that already exists). */ - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { json_object *json_path = NULL; path_cnt++; add_prefix_to_json = 1; @@ -2476,7 +2476,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type, if (json) json_path = json_object_new_array(); - route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, + route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path); if (json) @@ -2807,6 +2807,40 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn) } } +#ifndef VTYSH_EXTRACT_PL +#include "bgpd/bgp_evpn_vty_clippy.c" +#endif + +DEFPY(bgp_evpn_flood_control, + bgp_evpn_flood_control_cmd, + "[no$no] flooding ", + NO_STR + "Specify handling for BUM packets\n" + "Do not flood any BUM packets\n" + "Flood BUM packets using head-end replication\n") +{ + struct bgp *bgp = VTY_GET_CONTEXT(bgp); + enum vxlan_flood_control flood_ctrl; + + if (!bgp) + return CMD_WARNING; + + if (disable && !no) + flood_ctrl = VXLAN_FLOOD_DISABLED; + else if (her || no) + flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL; + else + return CMD_WARNING; + + if (bgp->vxlan_flood_ctrl == flood_ctrl) + return CMD_SUCCESS; + + bgp->vxlan_flood_ctrl = flood_ctrl; + bgp_evpn_flood_control_change(bgp); + + return CMD_SUCCESS; +} + DEFUN (bgp_evpn_advertise_default_gw_vni, bgp_evpn_advertise_default_gw_vni_cmd, "advertise-default-gw", @@ -3210,6 +3244,12 @@ DEFUN(show_bgp_l2vpn_evpn_vni, json_object_string_add(json, "advertiseAllVnis", is_evpn_enabled() ? "Enabled" : "Disabled"); + json_object_string_add( + json, "flooding", + bgp_def->vxlan_flood_ctrl + == VXLAN_FLOOD_HEAD_END_REPL + ? "Head-end replication" + : "Disabled"); json_object_int_add(json, "numVnis", num_vnis); json_object_int_add(json, "numL2Vnis", num_l2vnis); json_object_int_add(json, "numL3Vnis", num_l3vnis); @@ -3219,6 +3259,11 @@ DEFUN(show_bgp_l2vpn_evpn_vni, : "Disabled"); vty_out(vty, "Advertise All VNI flag: %s\n", is_evpn_enabled() ? "Enabled" : "Disabled"); + vty_out(vty, "BUM flooding: %s\n", + bgp_def->vxlan_flood_ctrl + == VXLAN_FLOOD_HEAD_END_REPL + ? "Head-end replication" + : "Disabled"); vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis); vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis); } @@ -3954,7 +3999,7 @@ DEFUN(test_withdraw_evpn_type4_route, } if (!bgp->peer_self) { - vty_out(vty, "%%BGP instance doesnt have self peer\n"); + vty_out(vty, "%%BGP instance doesn't have self peer\n"); return CMD_WARNING; } @@ -4874,6 +4919,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi, if (bgp->advertise_gw_macip) vty_out(vty, " advertise-default-gw\n"); + if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED) + vty_out(vty, " flooding disable\n"); + if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN], BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) { if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name) @@ -4965,6 +5013,7 @@ void bgp_ethernetvpn_init(void) install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd); install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd); install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd); + install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd); /* test commands */ install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd); diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c index c7977a9af4..1ccb8fb245 100644 --- a/bgpd/bgp_filter.c +++ b/bgpd/bgp_filter.c @@ -77,7 +77,7 @@ struct as_list { struct as_filter *tail; }; -/* ip as-path access-list 10 permit AS1. */ +/* as-path access-list 10 permit AS1. */ static struct as_list_master as_list_master = {{NULL, NULL}, {NULL, NULL}, @@ -401,9 +401,9 @@ static int config_bgp_aspath_validate(const char *regstr) return 0; } -DEFUN(ip_as_path, ip_as_path_cmd, - "ip as-path access-list WORD LINE...", - IP_STR +DEFUN(as_path, bgp_as_path_cmd, + "bgp as-path access-list WORD LINE...", + BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" "Regular expression access list name\n" @@ -418,6 +418,13 @@ DEFUN(ip_as_path, ip_as_path_cmd, regex_t *regex; char *regstr; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command\n"); + vty_out(vty, "'bgp as-path access-list WORD LINE'\n"); + zlog_warn("Deprecated option: 'ip as-path access-list WORD LINE' being used"); + } + /* Retrieve access list name */ argv_find(argv, argc, "WORD", &idx); char *alname = argv[idx]->arg; @@ -459,9 +466,23 @@ DEFUN(ip_as_path, ip_as_path_cmd, return CMD_SUCCESS; } -DEFUN(no_ip_as_path, no_ip_as_path_cmd, - "no ip as-path access-list WORD LINE...", - NO_STR IP_STR +#if CONFDATE > 20191005 +CPP_NOTICE("bgpd: remove deprecated 'ip as-path access-list WORD LINE' command") +#endif +ALIAS(as_path, ip_as_path_cmd, + "ip as-path access-list WORD LINE...", + IP_STR + "BGP autonomous system path filter\n" + "Specify an access list name\n" + "Regular expression access list name\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n") + +DEFUN(no_as_path, no_bgp_as_path_cmd, + "no bgp as-path access-list WORD LINE...", + NO_STR + BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" "Regular expression access list name\n" @@ -476,13 +497,19 @@ DEFUN(no_ip_as_path, no_ip_as_path_cmd, char *regstr; regex_t *regex; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command\n"); + vty_out(vty, "'no bgp as-path access-list WORD LINE'\n"); + zlog_warn("Deprecated option: 'no ip as-path access-list WORD LINE' being used"); + } char *aslistname = argv_find(argv, argc, "WORD", &idx) ? argv[idx]->arg : NULL; /* Lookup AS list from AS path list. */ aslist = as_list_lookup(aslistname); if (aslist == NULL) { - vty_out(vty, "ip as-path access-list %s doesn't exist\n", + vty_out(vty, "bgp as-path access-list %s doesn't exist\n", aslistname); return CMD_WARNING_CONFIG_FAILED; } @@ -530,21 +557,39 @@ DEFUN(no_ip_as_path, no_ip_as_path_cmd, return CMD_SUCCESS; } -DEFUN (no_ip_as_path_all, - no_ip_as_path_all_cmd, - "no ip as-path access-list WORD", +ALIAS(no_as_path, no_ip_as_path_cmd, + "no ip as-path access-list WORD LINE...", + NO_STR IP_STR + "BGP autonomous system path filter\n" + "Specify an access list name\n" + "Regular expression access list name\n" + "Specify packets to reject\n" + "Specify packets to forward\n" + "A regular-expression (1234567890_(^|[,{}() ]|$)) to match the BGP AS paths\n") + +DEFUN (no_as_path_all, + no_bgp_as_path_all_cmd, + "no bgp as-path access-list WORD", NO_STR - IP_STR + BGP_STR "BGP autonomous system path filter\n" "Specify an access list name\n" "Regular expression access list name\n") { int idx_word = 4; struct as_list *aslist; + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command\n"); + vty_out(vty, "'no bgp as-path access-list WORD'\n"); + zlog_warn("Deprecated option: `no ip as-path access-list WORD` being used"); + } aslist = as_list_lookup(argv[idx_word]->arg); if (aslist == NULL) { - vty_out(vty, "ip as-path access-list %s doesn't exist\n", + vty_out(vty, "bgp as-path access-list %s doesn't exist\n", argv[idx_word]->arg); return CMD_WARNING_CONFIG_FAILED; } @@ -558,6 +603,15 @@ DEFUN (no_ip_as_path_all, return CMD_SUCCESS; } +ALIAS (no_as_path_all, + no_ip_as_path_all_cmd, + "no ip as-path access-list WORD", + NO_STR + IP_STR + "BGP autonomous system path filter\n" + "Specify an access list name\n" + "Regular expression access list name\n") + static void as_list_show(struct vty *vty, struct as_list *aslist) { struct as_filter *asfilter; @@ -598,17 +652,24 @@ static void as_list_show_all(struct vty *vty) } } -DEFUN (show_ip_as_path_access_list, - show_ip_as_path_access_list_cmd, - "show ip as-path-access-list WORD", +DEFUN (show_as_path_access_list, + show_bgp_as_path_access_list_cmd, + "show bgp as-path-access-list WORD", SHOW_STR - IP_STR + BGP_STR "List AS path access lists\n" "AS path access list name\n") { int idx_word = 3; struct as_list *aslist; + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command\n"); + vty_out(vty, "'show bgp as-path-access-list WORD'\n"); + zlog_warn("Deprecated option: 'show ip as-path-access-list WORD' being used"); + } aslist = as_list_lookup(argv[idx_word]->arg); if (aslist) as_list_show(vty, aslist); @@ -616,16 +677,39 @@ DEFUN (show_ip_as_path_access_list, return CMD_SUCCESS; } -DEFUN (show_ip_as_path_access_list_all, +ALIAS (show_as_path_access_list, + show_ip_as_path_access_list_cmd, + "show ip as-path-access-list WORD", + SHOW_STR + IP_STR + "List AS path access lists\n" + "AS path access list name\n") + +DEFUN (show_as_path_access_list_all, + show_bgp_as_path_access_list_all_cmd, + "show bgp as-path-access-list", + SHOW_STR + BGP_STR + "List AS path access lists\n") +{ + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command\n"); + vty_out(vty, "'show bgp as-path-access-list'\n"); + zlog_warn("Deprecated option: 'show ip as-path-access-list' being used"); + } + as_list_show_all(vty); + return CMD_SUCCESS; +} + +ALIAS (show_as_path_access_list_all, show_ip_as_path_access_list_all_cmd, "show ip as-path-access-list", SHOW_STR IP_STR "List AS path access lists\n") -{ - as_list_show_all(vty); - return CMD_SUCCESS; -} static int config_write_as_list(struct vty *vty) { @@ -636,7 +720,7 @@ static int config_write_as_list(struct vty *vty) for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { - vty_out(vty, "ip as-path access-list %s %s %s\n", + vty_out(vty, "bgp as-path access-list %s %s %s\n", aslist->name, filter_type_str(asfilter->type), asfilter->reg_str); write++; @@ -645,7 +729,7 @@ static int config_write_as_list(struct vty *vty) for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) for (asfilter = aslist->head; asfilter; asfilter = asfilter->next) { - vty_out(vty, "ip as-path access-list %s %s %s\n", + vty_out(vty, "bgp as-path access-list %s %s %s\n", aslist->name, filter_type_str(asfilter->type), asfilter->reg_str); write++; @@ -660,11 +744,16 @@ void bgp_filter_init(void) { install_node(&as_list_node, config_write_as_list); + install_element(CONFIG_NODE, &bgp_as_path_cmd); install_element(CONFIG_NODE, &ip_as_path_cmd); + install_element(CONFIG_NODE, &no_bgp_as_path_cmd); install_element(CONFIG_NODE, &no_ip_as_path_cmd); + install_element(CONFIG_NODE, &no_bgp_as_path_all_cmd); install_element(CONFIG_NODE, &no_ip_as_path_all_cmd); + install_element(VIEW_NODE, &show_bgp_as_path_access_list_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_cmd); + install_element(VIEW_NODE, &show_bgp_as_path_access_list_all_cmd); install_element(VIEW_NODE, &show_ip_as_path_access_list_all_cmd); } diff --git a/bgpd/bgp_flowspec.h b/bgpd/bgp_flowspec.h index f07b696b8d..bc201b739f 100644 --- a/bgpd/bgp_flowspec.h +++ b/bgpd/bgp_flowspec.h @@ -44,8 +44,8 @@ extern void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, json_object *json_path); extern void route_vty_out_flowspec(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, - int display, json_object *json_paths); + struct bgp_path_info *path, int display, + json_object *json_paths); extern int bgp_fs_config_write_pbr(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi); diff --git a/bgpd/bgp_flowspec_vty.c b/bgpd/bgp_flowspec_vty.c index ceeecc7e19..4fb055bcc3 100644 --- a/bgpd/bgp_flowspec_vty.c +++ b/bgpd/bgp_flowspec_vty.c @@ -253,8 +253,8 @@ void bgp_fs_nlri_get_string(unsigned char *nlri_content, size_t len, } void route_vty_out_flowspec(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, - int display, json_object *json_paths) + struct bgp_path_info *path, int display, + json_object *json_paths) { struct attr *attr; char return_string[BGP_FLOWSPEC_STRING_DISPLAY_MAX]; @@ -274,9 +274,9 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, else json_nlri_path = json_paths; } - if (display == NLRI_STRING_FORMAT_LARGE && binfo) + if (display == NLRI_STRING_FORMAT_LARGE && path) vty_out(vty, "BGP flowspec entry: (flags 0x%x)\n", - binfo->flags); + path->flags); bgp_fs_nlri_get_string((unsigned char *) p->u.prefix_flowspec.ptr, p->u.prefix_flowspec.prefixlen, @@ -292,11 +292,11 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, else if (json_paths && display == NLRI_STRING_FORMAT_JSON) json_object_array_add(json_paths, json_nlri_path); } - if (!binfo) + if (!path) return; - if (binfo->attr && binfo->attr->ecommunity) { + if (path->attr && path->attr->ecommunity) { /* Print attribute */ - attr = binfo->attr; + attr = path->attr; s = ecommunity_ecom2str(attr->ecommunity, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); if (!s) @@ -318,7 +318,7 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, vty_out(vty, "\tNH %-16s\n", inet_ntoa(attr->nexthop)); XFREE(MTYPE_ECOMMUNITY_STR, s); } - peer_uptime(binfo->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL); + peer_uptime(path->uptime, timebuf, BGP_UPTIME_LEN, 0, NULL); if (display == NLRI_STRING_FORMAT_LARGE) { vty_out(vty, "\treceived for %8s\n", timebuf); } else if (json_paths) { @@ -329,7 +329,8 @@ void route_vty_out_flowspec(struct vty *vty, struct prefix *p, json_object_array_add(json_paths, json_time_path); } if (display == NLRI_STRING_FORMAT_LARGE) { - struct bgp_info_extra *extra = bgp_info_extra_get(binfo); + struct bgp_path_info_extra *extra = + bgp_path_info_extra_get(path); if (extra->bgp_fs_pbr) { struct listnode *node; @@ -368,7 +369,7 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, void *output_arg, bool use_json, int is_last, unsigned long *output_cum, unsigned long *total_cum) { - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_node *rn; unsigned long total_count = 0; json_object *json_paths = NULL; @@ -384,12 +385,10 @@ int bgp_show_table_flowspec(struct vty *vty, struct bgp *bgp, afi_t afi, json_paths = json_object_new_array(); display = NLRI_STRING_FORMAT_JSON; } - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { total_count++; - route_vty_out_flowspec(vty, &rn->p, - ri, display, + route_vty_out_flowspec(vty, &rn->p, pi, display, json_paths); - } if (use_json) { vty_out(vty, "%s\n", diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 65b8b5bd2d..8aa35eddfc 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -931,7 +931,7 @@ static void bgp_update_delay_process_status_change(struct peer *peer) } } -/* Called after event occured, this function change status and reset +/* Called after event occurred, this function change status and reset read/write and timer thread. */ void bgp_fsm_change_status(struct peer *peer, int status) { @@ -1677,6 +1677,15 @@ static int bgp_establish(struct peer *peer) peer_delete(peer->doppelganger); } + /* + * If we are replacing the old peer for a doppelganger + * then switch it around in the bgp->peerhash + * the doppelgangers su and this peer's su are the same + * so the hash_release is the same for either. + */ + hash_release(peer->bgp->peerhash, peer); + hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); + bgp_bfd_register_peer(peer); return ret; } 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_label.c b/bgpd/bgp_label.c index ba059d66e6..dcaaea6868 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -94,18 +94,18 @@ int bgp_parse_fec_update(void) return 1; } -mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, +mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_path_info *pi, struct peer *to, afi_t afi, safi_t safi) { struct peer *from; mpls_label_t remote_label; int reflect; - if (!rn || !ri || !to) + if (!rn || !pi || !to) return MPLS_INVALID_LABEL; - remote_label = ri->extra ? ri->extra->label[0] : MPLS_INVALID_LABEL; - from = ri->peer; + remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL; + from = pi->peer; reflect = ((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP)); @@ -120,7 +120,8 @@ mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, return rn->local_label; } -void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg) +void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_path_info *pi, + int reg) { struct stream *s; struct prefix *p; @@ -142,11 +143,11 @@ void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, int reg) stream_putw(s, PREFIX_FAMILY(p)); stream_put_prefix(s, p); if (reg) { - assert(ri); - if (ri->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { - if (ri->attr->label_index != BGP_INVALID_LABEL_INDEX) { + assert(pi); + if (pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID)) { + if (pi->attr->label_index != BGP_INVALID_LABEL_INDEX) { flags |= ZEBRA_FEC_REGISTER_LABEL_INDEX; - stream_putl(s, ri->attr->label_index); + stream_putl(s, pi->attr->label_index); } } SET_FLAG(rn->flags, BGP_NODE_REGISTERED_FOR_LABEL); diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h index 2b2525dd0e..b0fc07e547 100644 --- a/bgpd/bgp_label.h +++ b/bgpd/bgp_label.h @@ -27,13 +27,13 @@ #define BGP_PREVENT_VRF_2_VRF_LEAK 0xFFFFFFFE struct bgp_node; -struct bgp_info; +struct bgp_path_info; struct peer; -extern void bgp_reg_dereg_for_label(struct bgp_node *rn, struct bgp_info *ri, - int reg); +extern void bgp_reg_dereg_for_label(struct bgp_node *rn, + struct bgp_path_info *pi, int reg); extern int bgp_parse_fec_update(void); -extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_info *ri, +extern mpls_label_t bgp_adv_label(struct bgp_node *rn, struct bgp_path_info *pi, struct peer *to, afi_t afi, safi_t safi); extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, @@ -85,9 +85,9 @@ static inline void bgp_unset_valid_label(mpls_label_t *label) } static inline void bgp_register_for_label(struct bgp_node *rn, - struct bgp_info *ri) + struct bgp_path_info *pi) { - bgp_reg_dereg_for_label(rn, ri, 1); + bgp_reg_dereg_for_label(rn, pi, 1); } static inline void bgp_unregister_for_label(struct bgp_node *rn) 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_mpath.c b/bgpd/bgp_mpath.c index 333d09806e..241146e451 100644 --- a/bgpd/bgp_mpath.c +++ b/bgpd/bgp_mpath.c @@ -113,45 +113,47 @@ static int bgp_interface_same(struct interface *ifp1, struct interface *ifp2) /* - * bgp_info_nexthop_cmp + * bgp_path_info_nexthop_cmp * * Compare the nexthops of two paths. Return value is less than, equal to, - * or greater than zero if bi1 is respectively less than, equal to, - * or greater than bi2. + * or greater than zero if bpi1 is respectively less than, equal to, + * or greater than bpi2. */ -int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2) +int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, + struct bgp_path_info *bpi2) { int compare; struct in6_addr addr1, addr2; - compare = IPV4_ADDR_CMP(&bi1->attr->nexthop, &bi2->attr->nexthop); + compare = IPV4_ADDR_CMP(&bpi1->attr->nexthop, &bpi2->attr->nexthop); if (!compare) { - if (bi1->attr->mp_nexthop_len == bi2->attr->mp_nexthop_len) { - switch (bi1->attr->mp_nexthop_len) { + if (bpi1->attr->mp_nexthop_len == bpi2->attr->mp_nexthop_len) { + switch (bpi1->attr->mp_nexthop_len) { case BGP_ATTR_NHLEN_IPV4: case BGP_ATTR_NHLEN_VPNV4: compare = IPV4_ADDR_CMP( - &bi1->attr->mp_nexthop_global_in, - &bi2->attr->mp_nexthop_global_in); + &bpi1->attr->mp_nexthop_global_in, + &bpi2->attr->mp_nexthop_global_in); break; case BGP_ATTR_NHLEN_IPV6_GLOBAL: case BGP_ATTR_NHLEN_VPNV6_GLOBAL: compare = IPV6_ADDR_CMP( - &bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global); + &bpi1->attr->mp_nexthop_global, + &bpi2->attr->mp_nexthop_global); break; case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL: - addr1 = (bi1->attr->mp_nexthop_prefer_global) - ? bi1->attr->mp_nexthop_global - : bi1->attr->mp_nexthop_local; - addr2 = (bi2->attr->mp_nexthop_prefer_global) - ? bi2->attr->mp_nexthop_global - : bi2->attr->mp_nexthop_local; + addr1 = (bpi1->attr->mp_nexthop_prefer_global) + ? bpi1->attr->mp_nexthop_global + : bpi1->attr->mp_nexthop_local; + addr2 = (bpi2->attr->mp_nexthop_prefer_global) + ? bpi2->attr->mp_nexthop_global + : bpi2->attr->mp_nexthop_local; - if (!bi1->attr->mp_nexthop_prefer_global - && !bi2->attr->mp_nexthop_prefer_global) + if (!bpi1->attr->mp_nexthop_prefer_global + && !bpi2->attr->mp_nexthop_prefer_global) compare = !bgp_interface_same( - bi1->peer->ifp, bi2->peer->ifp); + bpi1->peer->ifp, + bpi2->peer->ifp); if (!compare) compare = IPV6_ADDR_CMP(&addr1, &addr2); @@ -163,14 +165,15 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2) * link-local * nexthops but another IPv6 peer only sends you global */ - else if (bi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL - || bi1->attr->mp_nexthop_len + else if (bpi1->attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL + || bpi1->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { - compare = IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global); + compare = IPV6_ADDR_CMP(&bpi1->attr->mp_nexthop_global, + &bpi2->attr->mp_nexthop_global); if (!compare) { - if (bi1->attr->mp_nexthop_len - < bi2->attr->mp_nexthop_len) + if (bpi1->attr->mp_nexthop_len + < bpi2->attr->mp_nexthop_len) compare = -1; else compare = 1; @@ -182,7 +185,7 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2) } /* - * bgp_info_mpath_cmp + * bgp_path_info_mpath_cmp * * This function determines our multipath list ordering. By ordering * the list we can deterministically select which paths are included @@ -193,26 +196,26 @@ int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2) * The order of paths is determined first by received nexthop, and then * by peer address if the nexthops are the same. */ -static int bgp_info_mpath_cmp(void *val1, void *val2) +static int bgp_path_info_mpath_cmp(void *val1, void *val2) { - struct bgp_info *bi1, *bi2; + struct bgp_path_info *bpi1, *bpi2; int compare; - bi1 = val1; - bi2 = val2; + bpi1 = val1; + bpi2 = val2; - compare = bgp_info_nexthop_cmp(bi1, bi2); + compare = bgp_path_info_nexthop_cmp(bpi1, bpi2); if (!compare) { - if (!bi1->peer->su_remote && !bi2->peer->su_remote) + if (!bpi1->peer->su_remote && !bpi2->peer->su_remote) compare = 0; - else if (!bi1->peer->su_remote) + else if (!bpi1->peer->su_remote) compare = 1; - else if (!bi2->peer->su_remote) + else if (!bpi2->peer->su_remote) compare = -1; else - compare = sockunion_cmp(bi1->peer->su_remote, - bi2->peer->su_remote); + compare = sockunion_cmp(bpi1->peer->su_remote, + bpi2->peer->su_remote); } return compare; @@ -228,7 +231,7 @@ void bgp_mp_list_init(struct list *mp_list) { assert(mp_list); memset(mp_list, 0, sizeof(struct list)); - mp_list->cmp = bgp_info_mpath_cmp; + mp_list->cmp = bgp_path_info_mpath_cmp; } /* @@ -247,31 +250,31 @@ void bgp_mp_list_clear(struct list *mp_list) * * Adds a multipath entry to the mp_list */ -void bgp_mp_list_add(struct list *mp_list, struct bgp_info *mpinfo) +void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo) { assert(mp_list && mpinfo); listnode_add_sort(mp_list, mpinfo); } /* - * bgp_info_mpath_new + * bgp_path_info_mpath_new * - * Allocate and zero memory for a new bgp_info_mpath element + * Allocate and zero memory for a new bgp_path_info_mpath element */ -static struct bgp_info_mpath *bgp_info_mpath_new(void) +static struct bgp_path_info_mpath *bgp_path_info_mpath_new(void) { - struct bgp_info_mpath *new_mpath; - new_mpath = - XCALLOC(MTYPE_BGP_MPATH_INFO, sizeof(struct bgp_info_mpath)); + struct bgp_path_info_mpath *new_mpath; + new_mpath = XCALLOC(MTYPE_BGP_MPATH_INFO, + sizeof(struct bgp_path_info_mpath)); return new_mpath; } /* - * bgp_info_mpath_free + * bgp_path_info_mpath_free * - * Release resources for a bgp_info_mpath element and zero out pointer + * Release resources for a bgp_path_info_mpath element and zero out pointer */ -void bgp_info_mpath_free(struct bgp_info_mpath **mpath) +void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath) { if (mpath && *mpath) { if ((*mpath)->mp_attr) @@ -282,37 +285,38 @@ void bgp_info_mpath_free(struct bgp_info_mpath **mpath) } /* - * bgp_info_mpath_get + * bgp_path_info_mpath_get * - * Fetch the mpath element for the given bgp_info. Used for + * Fetch the mpath element for the given bgp_path_info. Used for * doing lazy allocation. */ -static struct bgp_info_mpath *bgp_info_mpath_get(struct bgp_info *binfo) +static struct bgp_path_info_mpath * +bgp_path_info_mpath_get(struct bgp_path_info *path) { - struct bgp_info_mpath *mpath; - if (!binfo->mpath) { - mpath = bgp_info_mpath_new(); + struct bgp_path_info_mpath *mpath; + if (!path->mpath) { + mpath = bgp_path_info_mpath_new(); if (!mpath) return NULL; - binfo->mpath = mpath; - mpath->mp_info = binfo; + path->mpath = mpath; + mpath->mp_info = path; } - return binfo->mpath; + return path->mpath; } /* - * bgp_info_mpath_enqueue + * bgp_path_info_mpath_enqueue * * Enqueue a path onto the multipath list given the previous multipath * list entry */ -static void bgp_info_mpath_enqueue(struct bgp_info *prev_info, - struct bgp_info *binfo) +static void bgp_path_info_mpath_enqueue(struct bgp_path_info *prev_info, + struct bgp_path_info *path) { - struct bgp_info_mpath *prev, *mpath; + struct bgp_path_info_mpath *prev, *mpath; - prev = bgp_info_mpath_get(prev_info); - mpath = bgp_info_mpath_get(binfo); + prev = bgp_path_info_mpath_get(prev_info); + mpath = bgp_path_info_mpath_get(path); if (!prev || !mpath) return; @@ -322,17 +326,17 @@ static void bgp_info_mpath_enqueue(struct bgp_info *prev_info, prev->mp_next->mp_prev = mpath; prev->mp_next = mpath; - SET_FLAG(binfo->flags, BGP_INFO_MULTIPATH); + SET_FLAG(path->flags, BGP_PATH_MULTIPATH); } /* - * bgp_info_mpath_dequeue + * bgp_path_info_mpath_dequeue * * Remove a path from the multipath list */ -void bgp_info_mpath_dequeue(struct bgp_info *binfo) +void bgp_path_info_mpath_dequeue(struct bgp_path_info *path) { - struct bgp_info_mpath *mpath = binfo->mpath; + struct bgp_path_info_mpath *mpath = path->mpath; if (!mpath) return; if (mpath->mp_prev) @@ -340,101 +344,105 @@ void bgp_info_mpath_dequeue(struct bgp_info *binfo) if (mpath->mp_next) mpath->mp_next->mp_prev = mpath->mp_prev; mpath->mp_next = mpath->mp_prev = NULL; - UNSET_FLAG(binfo->flags, BGP_INFO_MULTIPATH); + UNSET_FLAG(path->flags, BGP_PATH_MULTIPATH); } /* - * bgp_info_mpath_next + * bgp_path_info_mpath_next * - * Given a bgp_info, return the next multipath entry + * Given a bgp_path_info, return the next multipath entry */ -struct bgp_info *bgp_info_mpath_next(struct bgp_info *binfo) +struct bgp_path_info *bgp_path_info_mpath_next(struct bgp_path_info *path) { - if (!binfo->mpath || !binfo->mpath->mp_next) + if (!path->mpath || !path->mpath->mp_next) return NULL; - return binfo->mpath->mp_next->mp_info; + return path->mpath->mp_next->mp_info; } /* - * bgp_info_mpath_first + * bgp_path_info_mpath_first * - * Given bestpath bgp_info, return the first multipath entry. + * Given bestpath bgp_path_info, return the first multipath entry. */ -struct bgp_info *bgp_info_mpath_first(struct bgp_info *binfo) +struct bgp_path_info *bgp_path_info_mpath_first(struct bgp_path_info *path) { - return bgp_info_mpath_next(binfo); + return bgp_path_info_mpath_next(path); } /* - * bgp_info_mpath_count + * bgp_path_info_mpath_count * - * Given the bestpath bgp_info, return the number of multipath entries + * Given the bestpath bgp_path_info, return the number of multipath entries */ -uint32_t bgp_info_mpath_count(struct bgp_info *binfo) +uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path) { - if (!binfo->mpath) + if (!path->mpath) return 0; - return binfo->mpath->mp_count; + return path->mpath->mp_count; } /* - * bgp_info_mpath_count_set + * bgp_path_info_mpath_count_set * * Sets the count of multipaths into bestpath's mpath element */ -static void bgp_info_mpath_count_set(struct bgp_info *binfo, uint32_t count) +static void bgp_path_info_mpath_count_set(struct bgp_path_info *path, + uint32_t count) { - struct bgp_info_mpath *mpath; - if (!count && !binfo->mpath) + struct bgp_path_info_mpath *mpath; + if (!count && !path->mpath) return; - mpath = bgp_info_mpath_get(binfo); + mpath = bgp_path_info_mpath_get(path); if (!mpath) return; mpath->mp_count = count; } /* - * bgp_info_mpath_attr + * bgp_path_info_mpath_attr * - * Given bestpath bgp_info, return aggregated attribute set used + * Given bestpath bgp_path_info, return aggregated attribute set used * for advertising the multipath route */ -struct attr *bgp_info_mpath_attr(struct bgp_info *binfo) +struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path) { - if (!binfo->mpath) + if (!path->mpath) return NULL; - return binfo->mpath->mp_attr; + return path->mpath->mp_attr; } /* - * bgp_info_mpath_attr_set + * bgp_path_info_mpath_attr_set * * Sets the aggregated attribute into bestpath's mpath element */ -static void bgp_info_mpath_attr_set(struct bgp_info *binfo, struct attr *attr) +static void bgp_path_info_mpath_attr_set(struct bgp_path_info *path, + struct attr *attr) { - struct bgp_info_mpath *mpath; - if (!attr && !binfo->mpath) + struct bgp_path_info_mpath *mpath; + if (!attr && !path->mpath) return; - mpath = bgp_info_mpath_get(binfo); + mpath = bgp_path_info_mpath_get(path); if (!mpath) return; mpath->mp_attr = attr; } /* - * bgp_info_mpath_update + * bgp_path_info_mpath_update * * Compare and sync up the multipath list with the mp_list generated by * bgp_best_selection */ -void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, - struct bgp_info *old_best, struct list *mp_list, - struct bgp_maxpaths_cfg *mpath_cfg) +void bgp_path_info_mpath_update(struct bgp_node *rn, + struct bgp_path_info *new_best, + struct bgp_path_info *old_best, + struct list *mp_list, + struct bgp_maxpaths_cfg *mpath_cfg) { uint16_t maxpaths, mpath_count, old_mpath_count; struct listnode *mp_node, *mp_next_node; - struct bgp_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; + struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath; int mpath_changed, debug; char pfx_buf[PREFIX2STR_BUFFER], nh_buf[2][INET6_ADDRSTRLEN]; char path_buf[PATH_ADDPATH_STR_BUFFER]; @@ -454,17 +462,17 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, if (new_best) { mpath_count++; if (new_best != old_best) - bgp_info_mpath_dequeue(new_best); + bgp_path_info_mpath_dequeue(new_best); maxpaths = (new_best->peer->sort == BGP_PEER_IBGP) ? mpath_cfg->maxpaths_ibgp : mpath_cfg->maxpaths_ebgp; } if (old_best) { - cur_mpath = bgp_info_mpath_first(old_best); - old_mpath_count = bgp_info_mpath_count(old_best); - bgp_info_mpath_count_set(old_best, 0); - bgp_info_mpath_dequeue(old_best); + cur_mpath = bgp_path_info_mpath_first(old_best); + old_mpath_count = bgp_path_info_mpath_count(old_best); + bgp_path_info_mpath_count_set(old_best, 0); + bgp_path_info_mpath_dequeue(old_best); } if (debug) @@ -485,7 +493,7 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, * to skip over it */ while (mp_node || cur_mpath) { - struct bgp_info *tmp_info; + struct bgp_path_info *tmp_info; /* * We can bail out of this loop if all existing paths on the @@ -496,7 +504,8 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, break; mp_next_node = mp_node ? listnextnode(mp_node) : NULL; - next_mpath = cur_mpath ? bgp_info_mpath_next(cur_mpath) : NULL; + next_mpath = + cur_mpath ? bgp_path_info_mpath_next(cur_mpath) : NULL; tmp_info = mp_node ? listgetdata(mp_node) : NULL; if (debug) @@ -512,14 +521,16 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, */ if (mp_node && (listgetdata(mp_node) == cur_mpath)) { list_delete_node(mp_list, mp_node); - bgp_info_mpath_dequeue(cur_mpath); + bgp_path_info_mpath_dequeue(cur_mpath); if ((mpath_count < maxpaths) - && bgp_info_nexthop_cmp(prev_mpath, cur_mpath)) { - bgp_info_mpath_enqueue(prev_mpath, cur_mpath); + && bgp_path_info_nexthop_cmp(prev_mpath, + cur_mpath)) { + bgp_path_info_mpath_enqueue(prev_mpath, + cur_mpath); prev_mpath = cur_mpath; mpath_count++; if (debug) { - bgp_info_path_with_addpath_rx_str( + bgp_path_info_path_with_addpath_rx_str( cur_mpath, path_buf); zlog_debug( "%s: %s is still multipath, cur count %d", @@ -528,7 +539,7 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, } else { mpath_changed = 1; if (debug) { - bgp_info_path_with_addpath_rx_str( + bgp_path_info_path_with_addpath_rx_str( cur_mpath, path_buf); zlog_debug( "%s: remove mpath %s nexthop %s, cur count %d", @@ -548,7 +559,8 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, if (cur_mpath && (!mp_node - || (bgp_info_mpath_cmp(cur_mpath, listgetdata(mp_node)) + || (bgp_path_info_mpath_cmp(cur_mpath, + listgetdata(mp_node)) < 0))) { /* * If here, we have an old multipath and either the @@ -557,11 +569,11 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, * multipath, so we need to purge this path from the * multipath list */ - bgp_info_mpath_dequeue(cur_mpath); + bgp_path_info_mpath_dequeue(cur_mpath); mpath_changed = 1; if (debug) { - bgp_info_path_with_addpath_rx_str(cur_mpath, - path_buf); + bgp_path_info_path_with_addpath_rx_str( + cur_mpath, path_buf); zlog_debug( "%s: remove mpath %s nexthop %s, cur count %d", pfx_buf, path_buf, @@ -595,17 +607,19 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, assert(new_mpath); assert(prev_mpath); if ((mpath_count < maxpaths) && (new_mpath != new_best) - && bgp_info_nexthop_cmp(prev_mpath, new_mpath)) { + && bgp_path_info_nexthop_cmp(prev_mpath, + new_mpath)) { if (new_mpath == next_mpath) - bgp_info_mpath_next(new_mpath); - bgp_info_mpath_dequeue(new_mpath); + bgp_path_info_mpath_next(new_mpath); + bgp_path_info_mpath_dequeue(new_mpath); - bgp_info_mpath_enqueue(prev_mpath, new_mpath); + bgp_path_info_mpath_enqueue(prev_mpath, + new_mpath); prev_mpath = new_mpath; mpath_changed = 1; mpath_count++; if (debug) { - bgp_info_path_with_addpath_rx_str( + bgp_path_info_path_with_addpath_rx_str( new_mpath, path_buf); zlog_debug( "%s: add mpath %s nexthop %s, cur count %d", @@ -629,39 +643,39 @@ void bgp_info_mpath_update(struct bgp_node *rn, struct bgp_info *new_best, pfx_buf, mpath_count, mpath_changed ? "YES" : "NO"); - bgp_info_mpath_count_set(new_best, mpath_count - 1); + bgp_path_info_mpath_count_set(new_best, mpath_count - 1); if (mpath_changed - || (bgp_info_mpath_count(new_best) != old_mpath_count)) - SET_FLAG(new_best->flags, BGP_INFO_MULTIPATH_CHG); + || (bgp_path_info_mpath_count(new_best) != old_mpath_count)) + SET_FLAG(new_best->flags, BGP_PATH_MULTIPATH_CHG); } } /* * bgp_mp_dmed_deselect * - * Clean up multipath information for BGP_INFO_DMED_SELECTED path that + * Clean up multipath information for BGP_PATH_DMED_SELECTED path that * is not selected as best path */ -void bgp_mp_dmed_deselect(struct bgp_info *dmed_best) +void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best) { - struct bgp_info *mpinfo, *mpnext; + struct bgp_path_info *mpinfo, *mpnext; if (!dmed_best) return; - for (mpinfo = bgp_info_mpath_first(dmed_best); mpinfo; + for (mpinfo = bgp_path_info_mpath_first(dmed_best); mpinfo; mpinfo = mpnext) { - mpnext = bgp_info_mpath_next(mpinfo); - bgp_info_mpath_dequeue(mpinfo); + mpnext = bgp_path_info_mpath_next(mpinfo); + bgp_path_info_mpath_dequeue(mpinfo); } - bgp_info_mpath_count_set(dmed_best, 0); - UNSET_FLAG(dmed_best->flags, BGP_INFO_MULTIPATH_CHG); - assert(bgp_info_mpath_first(dmed_best) == 0); + bgp_path_info_mpath_count_set(dmed_best, 0); + UNSET_FLAG(dmed_best->flags, BGP_PATH_MULTIPATH_CHG); + assert(bgp_path_info_mpath_first(dmed_best) == 0); } /* - * bgp_info_mpath_aggregate_update + * bgp_path_info_mpath_aggregate_update * * Set the multipath aggregate attribute. We need to see if the * aggregate has changed and then set the ATTR_CHANGED flag on the @@ -672,10 +686,10 @@ void bgp_mp_dmed_deselect(struct bgp_info *dmed_best) * is no change in multipath selection and no attribute change in * any multipath. */ -void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, - struct bgp_info *old_best) +void bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, + struct bgp_path_info *old_best) { - struct bgp_info *mpinfo; + struct bgp_path_info *mpinfo; struct aspath *aspath; struct aspath *asmerge; struct attr *new_attr, *old_attr; @@ -686,19 +700,19 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, struct attr attr = {0}; if (old_best && (old_best != new_best) - && (old_attr = bgp_info_mpath_attr(old_best))) { + && (old_attr = bgp_path_info_mpath_attr(old_best))) { bgp_attr_unintern(&old_attr); - bgp_info_mpath_attr_set(old_best, NULL); + bgp_path_info_mpath_attr_set(old_best, NULL); } if (!new_best) return; - if (!bgp_info_mpath_count(new_best)) { - if ((new_attr = bgp_info_mpath_attr(new_best))) { + if (!bgp_path_info_mpath_count(new_best)) { + if ((new_attr = bgp_path_info_mpath_attr(new_best))) { bgp_attr_unintern(&new_attr); - bgp_info_mpath_attr_set(new_best, NULL); - SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); + bgp_path_info_mpath_attr_set(new_best, NULL); + SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED); } return; } @@ -718,8 +732,8 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, lcomm = (attr.lcommunity) ? lcommunity_dup(attr.lcommunity) : NULL; - for (mpinfo = bgp_info_mpath_first(new_best); mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { + for (mpinfo = bgp_path_info_mpath_first(new_best); mpinfo; + mpinfo = bgp_path_info_mpath_next(mpinfo)) { asmerge = aspath_aggregate(aspath, mpinfo->attr->aspath); aspath_free(aspath); @@ -735,7 +749,7 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, mpinfo->attr->community); community = community_uniq_sort(commerge); - community_free(commerge); + community_free(&commerge); } else community = community_dup( mpinfo->attr->community); @@ -789,11 +803,11 @@ void bgp_info_mpath_aggregate_update(struct bgp_info *new_best, new_attr = bgp_attr_intern(&attr); - if (new_attr != bgp_info_mpath_attr(new_best)) { - if ((old_attr = bgp_info_mpath_attr(new_best))) + if (new_attr != bgp_path_info_mpath_attr(new_best)) { + if ((old_attr = bgp_path_info_mpath_attr(new_best))) bgp_attr_unintern(&old_attr); - bgp_info_mpath_attr_set(new_best, new_attr); - SET_FLAG(new_best->flags, BGP_INFO_ATTR_CHANGED); + bgp_path_info_mpath_attr_set(new_best, new_attr); + SET_FLAG(new_best->flags, BGP_PATH_ATTR_CHANGED); } else bgp_attr_unintern(&new_attr); } diff --git a/bgpd/bgp_mpath.h b/bgpd/bgp_mpath.h index 1fa11d3d0e..d15f3c9035 100644 --- a/bgpd/bgp_mpath.h +++ b/bgpd/bgp_mpath.h @@ -22,18 +22,18 @@ #ifndef _QUAGGA_BGP_MPATH_H #define _QUAGGA_BGP_MPATH_H -/* Supplemental information linked to bgp_info for keeping track of +/* Supplemental information linked to bgp_path_info for keeping track of * multipath selections, lazily allocated to save memory */ -struct bgp_info_mpath { +struct bgp_path_info_mpath { /* Points to the first multipath (on bestpath) or the next multipath */ - struct bgp_info_mpath *mp_next; + struct bgp_path_info_mpath *mp_next; /* Points to the previous multipath or NULL on bestpath */ - struct bgp_info_mpath *mp_prev; + struct bgp_path_info_mpath *mp_prev; - /* Points to bgp_info associated with this multipath info */ - struct bgp_info *mp_info; + /* Points to bgp_path_info associated with this multipath info */ + struct bgp_path_info *mp_info; /* When attached to best path, the number of selected multipaths */ uint32_t mp_count; @@ -50,27 +50,33 @@ extern int bgp_maximum_paths_unset(struct bgp *, afi_t, safi_t, int); /* Functions used by bgp_best_selection to record current * multipath selections */ -extern int bgp_info_nexthop_cmp(struct bgp_info *bi1, struct bgp_info *bi2); +extern int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1, + struct bgp_path_info *bpi2); extern void bgp_mp_list_init(struct list *); extern void bgp_mp_list_clear(struct list *); -extern void bgp_mp_list_add(struct list *, struct bgp_info *); -extern void bgp_mp_dmed_deselect(struct bgp_info *); -extern void bgp_info_mpath_update(struct bgp_node *, struct bgp_info *, - struct bgp_info *, struct list *, - struct bgp_maxpaths_cfg *); -extern void bgp_info_mpath_aggregate_update(struct bgp_info *, - struct bgp_info *); +extern void bgp_mp_list_add(struct list *mp_list, struct bgp_path_info *mpinfo); +extern void bgp_mp_dmed_deselect(struct bgp_path_info *dmed_best); +extern void bgp_path_info_mpath_update(struct bgp_node *rn, + struct bgp_path_info *new_best, + struct bgp_path_info *old_best, + struct list *mp_list, + struct bgp_maxpaths_cfg *mpath_cfg); +extern void +bgp_path_info_mpath_aggregate_update(struct bgp_path_info *new_best, + struct bgp_path_info *old_best); -/* Unlink and free multipath information associated with a bgp_info */ -extern void bgp_info_mpath_dequeue(struct bgp_info *); -extern void bgp_info_mpath_free(struct bgp_info_mpath **); +/* Unlink and free multipath information associated with a bgp_path_info */ +extern void bgp_path_info_mpath_dequeue(struct bgp_path_info *path); +extern void bgp_path_info_mpath_free(struct bgp_path_info_mpath **mpath); /* Walk list of multipaths associated with a best path */ -extern struct bgp_info *bgp_info_mpath_first(struct bgp_info *); -extern struct bgp_info *bgp_info_mpath_next(struct bgp_info *); +extern struct bgp_path_info * +bgp_path_info_mpath_first(struct bgp_path_info *path); +extern struct bgp_path_info * +bgp_path_info_mpath_next(struct bgp_path_info *path); /* Accessors for multipath information */ -extern uint32_t bgp_info_mpath_count(struct bgp_info *); -extern struct attr *bgp_info_mpath_attr(struct bgp_info *); +extern uint32_t bgp_path_info_mpath_count(struct bgp_path_info *path); +extern struct attr *bgp_path_info_mpath_attr(struct bgp_path_info *path); #endif /* _QUAGGA_BGP_MPATH_H */ diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 276945cbf6..385716970b 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -402,22 +402,23 @@ static int ecom_intersect(struct ecommunity *e1, struct ecommunity *e2) return 0; } -static bool labels_same(struct bgp_info *bi, mpls_label_t *label, uint32_t n) +static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label, + uint32_t n) { uint32_t i; - if (!bi->extra) { + if (!bpi->extra) { if (!n) return true; else return false; } - if (n != bi->extra->num_labels) + if (n != bpi->extra->num_labels) return false; for (i = 0; i < n; ++i) { - if (label[i] != bi->extra->label[i]) + if (label[i] != bpi->extra->label[i]) return false; } return true; @@ -426,22 +427,21 @@ static bool labels_same(struct bgp_info *bi, mpls_label_t *label, uint32_t n) /* * make encoded route labels match specified encoded label set */ -static void setlabels( - struct bgp_info *bi, - mpls_label_t *label, /* array of labels */ - uint32_t num_labels) +static void setlabels(struct bgp_path_info *bpi, + mpls_label_t *label, /* array of labels */ + uint32_t num_labels) { if (num_labels) assert(label); assert(num_labels <= BGP_MAX_LABELS); if (!num_labels) { - if (bi->extra) - bi->extra->num_labels = 0; + if (bpi->extra) + bpi->extra->num_labels = 0; return; } - struct bgp_info_extra *extra = bgp_info_extra_get(bi); + struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi); uint32_t i; for (i = 0; i < num_labels; ++i) { @@ -454,35 +454,27 @@ static void setlabels( } /* - * returns pointer to new bgp_info upon success + * returns pointer to new bgp_path_info upon success */ -static struct bgp_info * -leak_update( - struct bgp *bgp, /* destination bgp instance */ - struct bgp_node *bn, - struct attr *new_attr, /* already interned */ - afi_t afi, - safi_t safi, - struct bgp_info *source_bi, - mpls_label_t *label, - uint32_t num_labels, - void *parent, - struct bgp *bgp_orig, - struct prefix *nexthop_orig, - int nexthop_self_flag, - int debug) +static struct bgp_path_info * +leak_update(struct bgp *bgp, /* destination bgp instance */ + struct bgp_node *bn, struct attr *new_attr, /* already interned */ + afi_t afi, safi_t safi, struct bgp_path_info *source_bpi, + mpls_label_t *label, uint32_t num_labels, void *parent, + struct bgp *bgp_orig, struct prefix *nexthop_orig, + int nexthop_self_flag, int debug) { struct prefix *p = &bn->p; - struct bgp_info *bi; - struct bgp_info *bi_ultimate; - struct bgp_info *new; + struct bgp_path_info *bpi; + struct bgp_path_info *bpi_ultimate; + struct bgp_path_info *new; char buf_prefix[PREFIX_STRLEN]; if (debug) { prefix2str(&bn->p, buf_prefix, sizeof(buf_prefix)); zlog_debug("%s: entry: leak-to=%s, p=%s, type=%d, sub_type=%d", - __func__, bgp->name_pretty, buf_prefix, - source_bi->type, source_bi->sub_type); + __func__, bgp->name_pretty, buf_prefix, + source_bpi->type, source_bpi->sub_type); } /* @@ -494,31 +486,30 @@ leak_update( * should have nexthop tracking, we must find the ultimate * parent so we can check its sub_type. * - * As of now, source_bi may at most be a second-generation route + * As of now, source_bpi may at most be a second-generation route * (only one hop back to ultimate parent for vrf-vpn-vrf scheme). * Using a loop here supports more complex intra-bgp import-export * schemes that could be implemented in the future. * */ - for (bi_ultimate = source_bi; - bi_ultimate->extra && bi_ultimate->extra->parent; - bi_ultimate = bi_ultimate->extra->parent) - ; + for (bpi_ultimate = source_bpi; + bpi_ultimate->extra && bpi_ultimate->extra->parent; + bpi_ultimate = bpi_ultimate->extra->parent) + ; /* * match parent */ - for (bi = bn->info; bi; bi = bi->next) { - if (bi->extra && bi->extra->parent == parent) + for (bpi = bn->info; bpi; bpi = bpi->next) { + if (bpi->extra && bpi->extra->parent == parent) break; } - if (bi) { - bool labelssame = labels_same(bi, label, num_labels); + if (bpi) { + bool labelssame = labels_same(bpi, label, num_labels); - if (attrhash_cmp(bi->attr, new_attr) - && labelssame - && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(bpi->attr, new_attr) && labelssame + && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { bgp_attr_unintern(&new_attr); if (debug) @@ -530,43 +521,42 @@ leak_update( } /* attr is changed */ - bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED); /* Rewrite BGP route information. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) - bgp_info_restore(bn, bi); + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(bn, bpi); else - bgp_aggregate_decrement(bgp, p, bi, afi, safi); - bgp_attr_unintern(&bi->attr); - bi->attr = new_attr; - bi->uptime = bgp_clock(); + bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + bgp_attr_unintern(&bpi->attr); + bpi->attr = new_attr; + bpi->uptime = bgp_clock(); /* * rewrite labels */ if (!labelssame) - setlabels(bi, label, num_labels); + setlabels(bpi, label, num_labels); if (nexthop_self_flag) - bgp_info_set_flag(bn, bi, BGP_INFO_ANNC_NH_SELF); + bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF); struct bgp *bgp_nexthop = bgp; int nh_valid; - if (bi->extra && bi->extra->bgp_orig) - bgp_nexthop = bi->extra->bgp_orig; + if (bpi->extra && bpi->extra->bgp_orig) + bgp_nexthop = bpi->extra->bgp_orig; /* No nexthop tracking for redistributed routes */ - if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) + if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) nh_valid = 1; else /* * TBD do we need to do anything about the * 'connected' parameter? */ - nh_valid = bgp_find_or_add_nexthop( - bgp, bgp_nexthop, - afi, bi, NULL, 0); + nh_valid = bgp_find_or_add_nexthop(bgp, bgp_nexthop, + afi, bpi, NULL, 0); if (debug) zlog_debug("%s: nexthop is %svalid (in vrf %s)", @@ -574,10 +564,10 @@ leak_update( bgp_nexthop->name_pretty); if (nh_valid) - bgp_info_set_flag(bn, bi, BGP_INFO_VALID); + bgp_path_info_set_flag(bn, bpi, BGP_PATH_VALID); /* Process change. */ - bgp_aggregate_increment(bgp, p, bi, afi, safi); + bgp_aggregate_increment(bgp, p, bpi, afi, safi); bgp_process(bgp, bn, afi, safi); bgp_unlock_node(bn); @@ -585,22 +575,22 @@ leak_update( zlog_debug("%s: ->%s: %s Found route, changed attr", __func__, bgp->name_pretty, buf_prefix); - return bi; + return bpi; } new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0, bgp->peer_self, new_attr, bn); if (nexthop_self_flag) - bgp_info_set_flag(bn, new, BGP_INFO_ANNC_NH_SELF); + bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF); - bgp_info_extra_get(new); + bgp_path_info_extra_get(new); if (num_labels) setlabels(new, label, num_labels); - new->extra->parent = bgp_info_lock(parent); - bgp_lock_node((struct bgp_node *)((struct bgp_info *)parent)->net); + new->extra->parent = bgp_path_info_lock(parent); + bgp_lock_node((struct bgp_node *)((struct bgp_path_info *)parent)->net); if (bgp_orig) new->extra->bgp_orig = bgp_lock(bgp_orig); if (nexthop_orig) @@ -620,7 +610,7 @@ leak_update( * their originating protocols will do the tracking and * withdraw those routes if the nexthops become unreachable */ - if (bi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) + if (bpi_ultimate->sub_type == BGP_ROUTE_REDISTRIBUTE) nh_valid = 1; else /* @@ -635,10 +625,10 @@ leak_update( __func__, (nh_valid ? "" : "not "), bgp_nexthop->name_pretty); if (nh_valid) - bgp_info_set_flag(bn, new, BGP_INFO_VALID); + bgp_path_info_set_flag(bn, new, BGP_PATH_VALID); bgp_aggregate_increment(bgp, p, new, afi, safi); - bgp_info_add(bn, new); + bgp_path_info_add(bn, new); bgp_unlock_node(bn); bgp_process(bgp, bn, afi, safi); @@ -651,12 +641,12 @@ leak_update( } /* cf vnc_import_bgp_add_route_mode_nvegroup() and add_vnc_route() */ -void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ - struct bgp_info *info_vrf) /* route */ +void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ + struct bgp *bgp_vrf, /* from */ + struct bgp_path_info *path_vrf) /* route */ { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); - struct prefix *p = &info_vrf->net->p; + struct prefix *p = &path_vrf->net->p; afi_t afi = family2afi(p->family); struct attr static_attr = {0}; struct attr *new_attr = NULL; @@ -670,12 +660,12 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ if (debug) zlog_debug("%s: from vrf %s", __func__, bgp_vrf->name_pretty); - if (debug && info_vrf->attr->ecommunity) { - char *s = ecommunity_ecom2str(info_vrf->attr->ecommunity, + if (debug && path_vrf->attr->ecommunity) { + char *s = ecommunity_ecom2str(path_vrf->attr->ecommunity, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); - zlog_debug("%s: %s info_vrf->type=%d, EC{%s}", __func__, - bgp_vrf->name, info_vrf->type, s); + zlog_debug("%s: %s path_vrf->type=%d, EC{%s}", __func__, + bgp_vrf->name, path_vrf->type, s); XFREE(MTYPE_ECOMMUNITY_STR, s); } @@ -689,7 +679,7 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ } /* loop check - should not be an imported route. */ - if (info_vrf->extra && info_vrf->extra->bgp_orig) + if (path_vrf->extra && path_vrf->extra->bgp_orig) return; @@ -700,13 +690,13 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ return; } - bgp_attr_dup(&static_attr, info_vrf->attr); /* shallow copy */ + bgp_attr_dup(&static_attr, path_vrf->attr); /* shallow copy */ /* * route map handling */ if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_TOVPN]) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -818,8 +808,8 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ * IPv4 nexthops as the attr has been copied * otherwise. */ - if (afi == AFI_IP && - !BGP_ATTR_NEXTHOP_AFI_IP6(info_vrf->attr)) { + if (afi == AFI_IP + && !BGP_ATTR_NEXTHOP_AFI_IP6(path_vrf->attr)) { static_attr.mp_nexthop_global_in.s_addr = static_attr.nexthop.s_addr; static_attr.mp_nexthop_len = 4; @@ -859,10 +849,10 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p, &(bgp_vrf->vpn_policy[afi].tovpn_rd)); - struct bgp_info *new_info; + struct bgp_path_info *new_info; - new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, info_vrf, - &label, 1, info_vrf, bgp_vrf, NULL, + new_info = leak_update(bgp_vpn, bn, new_attr, afi, safi, path_vrf, + &label, 1, path_vrf, bgp_vrf, NULL, nexthop_self_flag, debug); /* @@ -878,15 +868,15 @@ void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, /* to */ vpn_leak_to_vrf_update(bgp_vrf, new_info); } -void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ - struct bgp *bgp_vrf, /* from */ - struct bgp_info *info_vrf) /* route */ +void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ + struct bgp *bgp_vrf, /* from */ + struct bgp_path_info *path_vrf) /* route */ { int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); - struct prefix *p = &info_vrf->net->p; + struct prefix *p = &path_vrf->net->p; afi_t afi = family2afi(p->family); safi_t safi = SAFI_MPLS_VPN; - struct bgp_info *bi; + struct bgp_path_info *bpi; struct bgp_node *bn; const char *debugmsg; char buf_prefix[PREFIX_STRLEN]; @@ -896,16 +886,16 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ zlog_debug( "%s: entry: leak-from=%s, p=%s, type=%d, sub_type=%d", __func__, bgp_vrf->name_pretty, buf_prefix, - info_vrf->type, info_vrf->sub_type); + path_vrf->type, path_vrf->sub_type); } - if (info_vrf->sub_type != BGP_ROUTE_NORMAL - && info_vrf->sub_type != BGP_ROUTE_STATIC - && info_vrf->sub_type != BGP_ROUTE_REDISTRIBUTE) { + if (path_vrf->sub_type != BGP_ROUTE_NORMAL + && path_vrf->sub_type != BGP_ROUTE_STATIC + && path_vrf->sub_type != BGP_ROUTE_REDISTRIBUTE) { if (debug) zlog_debug("%s: wrong sub_type %d", __func__, - info_vrf->sub_type); + path_vrf->sub_type); return; } if (!bgp_vpn) @@ -924,27 +914,27 @@ void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, /* to */ } if (debug) - zlog_debug("%s: withdrawing (info_vrf=%p)", __func__, info_vrf); + zlog_debug("%s: withdrawing (path_vrf=%p)", __func__, path_vrf); bn = bgp_afi_node_get(bgp_vpn->rib[afi][safi], afi, safi, p, &(bgp_vrf->vpn_policy[afi].tovpn_rd)); /* * vrf -> vpn - * match original bi imported from + * match original bpi imported from */ - for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) { - if (bi->extra && bi->extra->parent == info_vrf) { + for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { + if (bpi->extra && bpi->extra->parent == path_vrf) { break; } } - if (bi) { + if (bpi) { /* withdraw from looped vrfs as well */ - vpn_leak_to_vrf_withdraw(bgp_vpn, bi); + vpn_leak_to_vrf_withdraw(bgp_vpn, bpi); - bgp_aggregate_decrement(bgp_vpn, p, bi, afi, safi); - bgp_info_delete(bn, bi); + bgp_aggregate_decrement(bgp_vpn, p, bpi, afi, safi); + bgp_path_info_delete(bn, bpi); bgp_process(bgp_vpn, bn, afi, safi); } bgp_unlock_node(bn); @@ -959,14 +949,14 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ safi_t safi = SAFI_MPLS_VPN; /* - * Walk vpn table, delete bi with bgp_orig == bgp_vrf + * Walk vpn table, delete bpi with bgp_orig == bgp_vrf */ for (prn = bgp_table_top(bgp_vpn->rib[afi][safi]); prn; prn = bgp_route_next(prn)) { struct bgp_table *table; struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; /* This is the per-RD table of prefixes */ table = prn->info; @@ -984,24 +974,24 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */ prefix2str(&bn->p, buf, sizeof(buf))); } - for (bi = bn->info; bi; bi = bi->next) { + for (bpi = bn->info; bpi; bpi = bpi->next) { if (debug) zlog_debug("%s: type %d, sub_type %d", - __func__, bi->type, - bi->sub_type); - if (bi->sub_type != BGP_ROUTE_IMPORTED) + __func__, bpi->type, + bpi->sub_type); + if (bpi->sub_type != BGP_ROUTE_IMPORTED) continue; - if (!bi->extra) + if (!bpi->extra) continue; - if ((struct bgp *)bi->extra->bgp_orig + if ((struct bgp *)bpi->extra->bgp_orig == bgp_vrf) { /* delete route */ if (debug) zlog_debug("%s: deleting it\n", __func__); bgp_aggregate_decrement(bgp_vpn, &bn->p, - bi, afi, safi); - bgp_info_delete(bn, bi); + bpi, afi, safi); + bgp_path_info_delete(bn, bpi); bgp_process(bgp_vpn, bn, afi, safi); } } @@ -1014,7 +1004,7 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ afi_t afi) { struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; int debug = BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF); if (debug) @@ -1027,21 +1017,22 @@ void vpn_leak_from_vrf_update_all(struct bgp *bgp_vpn, /* to */ if (debug) zlog_debug("%s: node=%p", __func__, bn); - for (bi = bn->info; bi; bi = bi->next) { + for (bpi = bn->info; bpi; bpi = bpi->next) { if (debug) zlog_debug( "%s: calling vpn_leak_from_vrf_update", __func__); - vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bi); + vpn_leak_from_vrf_update(bgp_vpn, bgp_vrf, bpi); } } } -static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ - struct bgp *bgp_vpn, /* from */ - struct bgp_info *info_vpn) /* route */ +static void +vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ + struct bgp *bgp_vpn, /* from */ + struct bgp_path_info *path_vpn) /* route */ { - struct prefix *p = &info_vpn->net->p; + struct prefix *p = &path_vpn->net->p; afi_t afi = family2afi(p->family); struct attr static_attr = {0}; @@ -1053,7 +1044,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ mpls_label_t *pLabels = NULL; uint32_t num_labels = 0; int nexthop_self_flag = 1; - struct bgp_info *bi_ultimate = NULL; + struct bgp_path_info *bpi_ultimate = NULL; int origin_local = 0; struct bgp *src_vrf; @@ -1068,7 +1059,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ /* Check for intersection of route targets */ if (!ecom_intersect( bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN], - info_vpn->attr->ecommunity)) { + path_vpn->attr->ecommunity)) { return; } @@ -1077,7 +1068,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ zlog_debug("%s: updating to vrf %s", __func__, bgp_vrf->name_pretty); - bgp_attr_dup(&static_attr, info_vpn->attr); /* shallow copy */ + bgp_attr_dup(&static_attr, path_vpn->attr); /* shallow copy */ /* * Nexthop: stash and clear @@ -1086,15 +1077,17 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ * Stash it for later label resolution by vrf ingress path and then * overwrite with 0, i.e., "me", for the sake of vrf advertisement. */ - uint8_t nhfamily = NEXTHOP_FAMILY(info_vpn->attr->mp_nexthop_len); + uint8_t nhfamily = NEXTHOP_FAMILY(path_vpn->attr->mp_nexthop_len); + if (nhfamily != AF_UNSPEC) + static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); memset(&nexthop_orig, 0, sizeof(nexthop_orig)); nexthop_orig.family = nhfamily; switch (nhfamily) { case AF_INET: /* save */ - nexthop_orig.u.prefix4 = info_vpn->attr->mp_nexthop_global_in; + nexthop_orig.u.prefix4 = path_vpn->attr->mp_nexthop_global_in; nexthop_orig.prefixlen = 32; if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi], @@ -1103,15 +1096,14 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ nexthop_orig.u.prefix4.s_addr; static_attr.mp_nexthop_global_in = - info_vpn->attr->mp_nexthop_global_in; + path_vpn->attr->mp_nexthop_global_in; static_attr.mp_nexthop_len = - info_vpn->attr->mp_nexthop_len; + path_vpn->attr->mp_nexthop_len; } - static_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); break; case AF_INET6: /* save */ - nexthop_orig.u.prefix6 = info_vpn->attr->mp_nexthop_global; + nexthop_orig.u.prefix6 = path_vpn->attr->mp_nexthop_global; nexthop_orig.prefixlen = 128; if (CHECK_FLAG(bgp_vrf->af_flags[afi][safi], @@ -1125,7 +1117,7 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ * route map handling */ if (bgp_vrf->vpn_policy[afi].rmap[BGP_VPN_POLICY_DIR_FROMVPN]) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -1173,30 +1165,30 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ if (!CHECK_FLAG(bgp_vrf->af_flags[afi][safi], BGP_CONFIG_VRF_TO_VRF_IMPORT)) { /* work back to original route */ - for (bi_ultimate = info_vpn; - bi_ultimate->extra && bi_ultimate->extra->parent; - bi_ultimate = bi_ultimate->extra->parent) + for (bpi_ultimate = path_vpn; + bpi_ultimate->extra && bpi_ultimate->extra->parent; + bpi_ultimate = bpi_ultimate->extra->parent) ; /* * if original route was unicast, * then it did not arrive over vpn */ - if (bi_ultimate->net) { + if (bpi_ultimate->net) { struct bgp_table *table; - table = bgp_node_table(bi_ultimate->net); + table = bgp_node_table(bpi_ultimate->net); if (table && (table->safi == SAFI_UNICAST)) origin_local = 1; } /* copy labels */ - if (!origin_local && - info_vpn->extra && info_vpn->extra->num_labels) { - num_labels = info_vpn->extra->num_labels; + if (!origin_local && path_vpn->extra + && path_vpn->extra->num_labels) { + num_labels = path_vpn->extra->num_labels; if (num_labels > BGP_MAX_LABELS) num_labels = BGP_MAX_LABELS; - pLabels = info_vpn->extra->label; + pLabels = path_vpn->extra->label; } } @@ -1211,19 +1203,18 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf, /* to */ * For VRF-2-VRF route-leaking, * the source will be the originating VRF. */ - if (info_vpn->extra && info_vpn->extra->bgp_orig) - src_vrf = info_vpn->extra->bgp_orig; + if (path_vpn->extra && path_vpn->extra->bgp_orig) + src_vrf = path_vpn->extra->bgp_orig; else src_vrf = bgp_vpn; - leak_update(bgp_vrf, bn, new_attr, afi, safi, info_vpn, - pLabels, num_labels, - info_vpn, /* parent */ - src_vrf, &nexthop_orig, nexthop_self_flag, debug); + leak_update(bgp_vrf, bn, new_attr, afi, safi, path_vpn, pLabels, + num_labels, path_vpn, /* parent */ + src_vrf, &nexthop_orig, nexthop_self_flag, debug); } -void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */ - struct bgp_info *info_vpn) /* route */ +void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */ + struct bgp_path_info *path_vpn) /* route */ { struct listnode *mnode, *mnnode; struct bgp *bgp; @@ -1231,20 +1222,20 @@ void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, /* from */ int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); if (debug) - zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn); + zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn); /* Loop over VRFs */ for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) { - if (!info_vpn->extra - || info_vpn->extra->bgp_orig != bgp) { /* no loop */ - vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, info_vpn); + if (!path_vpn->extra + || path_vpn->extra->bgp_orig != bgp) { /* no loop */ + vpn_leak_to_vrf_update_onevrf(bgp, bgp_vpn, path_vpn); } } } -void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ - struct bgp_info *info_vpn) /* route */ +void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ + struct bgp_path_info *path_vpn) /* route */ { struct prefix *p; afi_t afi; @@ -1252,38 +1243,38 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ struct bgp *bgp; struct listnode *mnode, *mnnode; struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; const char *debugmsg; char buf_prefix[PREFIX_STRLEN]; int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); if (debug) { - prefix2str(&info_vpn->net->p, buf_prefix, sizeof(buf_prefix)); - zlog_debug("%s: entry: p=%s, type=%d, sub_type=%d", - __func__, buf_prefix, - info_vpn->type, info_vpn->sub_type); + prefix2str(&path_vpn->net->p, buf_prefix, sizeof(buf_prefix)); + zlog_debug("%s: entry: p=%s, type=%d, sub_type=%d", __func__, + buf_prefix, path_vpn->type, path_vpn->sub_type); } if (debug) - zlog_debug("%s: start (info_vpn=%p)", __func__, info_vpn); + zlog_debug("%s: start (path_vpn=%p)", __func__, path_vpn); - if (!info_vpn->net) { + if (!path_vpn->net) { #if ENABLE_BGP_VNC - /* BGP_ROUTE_RFP routes do not have info_vpn->net set (yet) */ - if (info_vpn->type == ZEBRA_ROUTE_BGP && - info_vpn->sub_type == BGP_ROUTE_RFP) { + /* BGP_ROUTE_RFP routes do not have path_vpn->net set (yet) */ + if (path_vpn->type == ZEBRA_ROUTE_BGP + && path_vpn->sub_type == BGP_ROUTE_RFP) { return; } #endif if (debug) - zlog_debug("%s: info_vpn->net unexpectedly NULL, no prefix, bailing", + zlog_debug( + "%s: path_vpn->net unexpectedly NULL, no prefix, bailing", __func__); return; } - p = &info_vpn->net->p; + p = &path_vpn->net->p; afi = family2afi(p->family); /* Loop over VRFs */ @@ -1298,7 +1289,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ /* Check for intersection of route targets */ if (!ecom_intersect(bgp->vpn_policy[afi] .rtlist[BGP_VPN_POLICY_DIR_FROMVPN], - info_vpn->attr->ecommunity)) { + path_vpn->attr->ecommunity)) { continue; } @@ -1308,19 +1299,20 @@ void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, /* from */ bgp->name_pretty); bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); - for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) { - if (bi->extra - && (struct bgp_info *)bi->extra->parent - == info_vpn) { + for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { + if (bpi->extra + && (struct bgp_path_info *)bpi->extra->parent + == path_vpn) { break; } } - if (bi) { + if (bpi) { if (debug) - zlog_debug("%s: deleting bi %p", __func__, bi); - bgp_aggregate_decrement(bgp, p, bi, afi, safi); - bgp_info_delete(bn, bi); + zlog_debug("%s: deleting bpi %p", __func__, + bpi); + bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + bgp_path_info_delete(bn, bpi); bgp_process(bgp, bn, afi, safi); } bgp_unlock_node(bn); @@ -1331,25 +1323,25 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *bgp_vrf, /* to */ afi_t afi) { struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; safi_t safi = SAFI_UNICAST; int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF); if (debug) zlog_debug("%s: entry", __func__); /* - * Walk vrf table, delete bi with bgp_orig in a different vrf + * Walk vrf table, delete bpi with bgp_orig in a different vrf */ for (bn = bgp_table_top(bgp_vrf->rib[afi][safi]); bn; bn = bgp_route_next(bn)) { - for (bi = bn->info; bi; bi = bi->next) { - if (bi->extra && bi->extra->bgp_orig != bgp_vrf) { + for (bpi = bn->info; bpi; bpi = bpi->next) { + if (bpi->extra && bpi->extra->bgp_orig != bgp_vrf) { /* delete route */ - bgp_aggregate_decrement(bgp_vrf, &bn->p, bi, + bgp_aggregate_decrement(bgp_vrf, &bn->p, bpi, afi, safi); - bgp_info_delete(bn, bi); + bgp_path_info_delete(bn, bpi); bgp_process(bgp_vrf, bn, afi, safi); } } @@ -1374,7 +1366,7 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ struct bgp_table *table; struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; memset(&prd, 0, sizeof(prd)); prd.family = AF_UNSPEC; @@ -1389,13 +1381,14 @@ void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, /* to */ for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) { - for (bi = bn->info; bi; bi = bi->next) { + for (bpi = bn->info; bpi; bpi = bpi->next) { - if (bi->extra && bi->extra->bgp_orig == bgp_vrf) + if (bpi->extra + && bpi->extra->bgp_orig == bgp_vrf) continue; vpn_leak_to_vrf_update_onevrf(bgp_vrf, bgp_vpn, - bi); + bpi); } } } diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h index 61b87392a2..5b989e1853 100644 --- a/bgpd/bgp_mplsvpn.h +++ b/bgpd/bgp_mplsvpn.h @@ -53,10 +53,10 @@ extern int bgp_show_mpls_vpn(struct vty *vty, afi_t afi, struct prefix_rd *prd, int tags, bool use_json); extern void vpn_leak_from_vrf_update(struct bgp *bgp_vpn, struct bgp *bgp_vrf, - struct bgp_info *info_vrf); + struct bgp_path_info *path_vrf); extern void vpn_leak_from_vrf_withdraw(struct bgp *bgp_vpn, struct bgp *bgp_vrf, - struct bgp_info *info_vrf); + struct bgp_path_info *path_vrf); extern void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, struct bgp *bgp_vrf, afi_t afi); @@ -70,10 +70,10 @@ extern void vpn_leak_to_vrf_update_all(struct bgp *bgp_vrf, struct bgp *bgp_vpn, afi_t afi); extern void vpn_leak_to_vrf_update(struct bgp *bgp_vpn, - struct bgp_info *info_vpn); + struct bgp_path_info *path_vpn); extern void vpn_leak_to_vrf_withdraw(struct bgp *bgp_vpn, - struct bgp_info *info_vpn); + struct bgp_path_info *path_vpn); extern void vpn_leak_zebra_vrf_label_update(struct bgp *bgp, afi_t afi); extern void vpn_leak_zebra_vrf_label_withdraw(struct bgp *bgp, afi_t afi); diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index d56fdd75ce..191b1641b2 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -406,7 +406,6 @@ static int bgp_accept(struct thread *thread) peer = peer_create(&su, peer1->conf_if, peer1->bgp, peer1->local_as, peer1->as, peer1->as_type, 0, 0, NULL); - peer->su = su; hash_release(peer->bgp->peerhash, peer); hash_get(peer->bgp->peerhash, peer, hash_alloc_intern); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index ce7f5b40f5..5ed6fd6ebe 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -47,6 +47,8 @@ #include "zebra/rib.h" #include "zebra/zserv.h" /* For ZEBRA_SERV_PATH. */ +DEFINE_MTYPE_STATIC(BGPD, MARTIAN_STRING, "BGP Martian Address Intf String"); + char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size) { prefix2str(&(bnc->node->p), buf, size); @@ -82,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); } } @@ -114,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; @@ -205,7 +214,7 @@ static void bgp_address_hash_string_del(void *val) { char *data = val; - XFREE(MTYPE_TMP, data); + XFREE(MTYPE_MARTIAN_STRING, data); } static void *bgp_address_hash_alloc(void *p) @@ -237,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; @@ -278,7 +287,7 @@ static void bgp_address_add(struct bgp *bgp, struct connected *ifc, break; } if (!node) { - name = XSTRDUP(MTYPE_TMP, ifc->ifp->name); + name = XSTRDUP(MTYPE_MARTIAN_STRING, ifc->ifp->name); listnode_add(addr->ifp_name_list, name); } } @@ -303,8 +312,10 @@ static void bgp_address_del(struct bgp *bgp, struct connected *ifc, break; } - if (node) + if (node) { list_delete_node(addr->ifp_name_list, node); + XFREE(MTYPE_MARTIAN_STRING, name); + } if (addr->ifp_name_list->count == 0) { hash_release(bgp->address_hash, addr); diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 1cb05bc853..f06fae5706 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -63,7 +63,7 @@ struct bgp_nexthop_cache { struct bgp_node *node; void *nht_info; /* In BGP, peer session */ - LIST_HEAD(path_list, bgp_info) paths; + LIST_HEAD(path_list, bgp_path_info) paths; unsigned int path_count; struct bgp *bgp; }; @@ -74,8 +74,6 @@ struct tip_addr { int refcnt; }; -extern int bgp_nexthop_lookup(afi_t, struct peer *peer, struct bgp_info *, - int *, int *); extern void bgp_connected_add(struct bgp *bgp, struct connected *c); extern void bgp_connected_delete(struct bgp *bgp, struct connected *c); extern int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index dd1ffe9f3b..e764860bcc 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -50,9 +50,7 @@ static void register_zebra_rnh(struct bgp_nexthop_cache *bnc, 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_info *ri, struct prefix *p); -static void path_nh_map(struct bgp_info *path, struct bgp_nexthop_cache *bnc, - int keep); +static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p); static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc) { @@ -66,7 +64,7 @@ static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc) || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID))); } -int bgp_find_nexthop(struct bgp_info *path, int connected) +int bgp_find_nexthop(struct bgp_path_info *path, int connected) { struct bgp_nexthop_cache *bnc = path->nexthop; @@ -104,14 +102,14 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc) } } -void bgp_unlink_nexthop(struct bgp_info *path) +void bgp_unlink_nexthop(struct bgp_path_info *path) { struct bgp_nexthop_cache *bnc = path->nexthop; if (!bnc) return; - path_nh_map(path, NULL, 0); + path_nh_map(path, NULL, false); bgp_unlink_nexthop_check(bnc); } @@ -143,7 +141,7 @@ void bgp_unlink_nexthop_by_peer(struct peer *peer) * we need both the bgp_route and bgp_nexthop pointers. */ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, - afi_t afi, struct bgp_info *ri, + afi_t afi, struct bgp_path_info *pi, struct peer *peer, int connected) { struct bgp_node *rn; @@ -151,9 +149,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, struct prefix p; int is_bgp_static_route = 0; - if (ri) { - is_bgp_static_route = ((ri->type == ZEBRA_ROUTE_BGP) - && (ri->sub_type == BGP_ROUTE_STATIC)) + if (pi) { + is_bgp_static_route = ((pi->type == ZEBRA_ROUTE_BGP) + && (pi->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; @@ -161,19 +159,14 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, to derive address-family from the next-hop. */ if (!is_bgp_static_route) - afi = BGP_ATTR_NEXTHOP_AFI_IP6(ri->attr) ? AFI_IP6 + afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6 : AFI_IP; /* This will return TRUE if the global IPv6 NH is a link local * addr */ - if (make_prefix(afi, ri, &p) < 0) + if (make_prefix(afi, pi, &p) < 0) return 1; } else if (peer) { - /* Don't register link local NH */ - if (afi == AFI_IP6 - && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) - return 1; - if (!sockunion2hostprefix(&peer->su, &p)) { if (BGP_DEBUG(nht, NHT)) { zlog_debug( @@ -251,19 +244,20 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, bnc->flags |= BGP_NEXTHOP_VALID; } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) register_zebra_rnh(bnc, is_bgp_static_route); - if (ri && ri->nexthop != bnc) { + if (pi && pi->nexthop != bnc) { /* Unlink from existing nexthop cache, if any. This will also * free * the nexthop cache entry, if appropriate. */ - bgp_unlink_nexthop(ri); + bgp_unlink_nexthop(pi); - path_nh_map(ri, bnc, 1); /* updates NHT ri list reference */ + /* updates NHT pi list reference */ + path_nh_map(pi, bnc, true); if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric) - (bgp_info_extra_get(ri))->igpmetric = bnc->metric; - else if (ri->extra) - ri->extra->igpmetric = 0; + (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric; + else if (pi->extra) + pi->extra->igpmetric = 0; } else if (peer) bnc->nht_info = (void *)peer; /* NHT peer reference */ @@ -287,10 +281,6 @@ void bgp_delete_connected_nexthop(afi_t afi, struct peer *peer) if (!peer) return; - /* We don't register link local address for NHT */ - if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr)) - return; - if (!sockunion2hostprefix(&peer->su, &p)) return; @@ -437,8 +427,9 @@ void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id) * we receive from bgp. This is to allow us * to work with v4 routing over v6 nexthops */ - if (peer && - CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE) + if (peer && !peer->ifp + && CHECK_FLAG(peer->flags, + PEER_FLAG_CAPABILITY_ENHE) && nhr.prefix.family == AF_INET6) { struct interface *ifp; @@ -535,11 +526,11 @@ void bgp_cleanup_nexthops(struct bgp *bgp) * make_prefix - make a prefix structure from the path (essentially * path's node. */ -static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p) +static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p) { - int is_bgp_static = ((ri->type == ZEBRA_ROUTE_BGP) - && (ri->sub_type == BGP_ROUTE_STATIC)) + int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP) + && (pi->sub_type == BGP_ROUTE_STATIC)) ? 1 : 0; @@ -548,26 +539,21 @@ static int make_prefix(int afi, struct bgp_info *ri, struct prefix *p) case AFI_IP: p->family = AF_INET; if (is_bgp_static) { - p->u.prefix4 = ri->net->p.u.prefix4; - p->prefixlen = ri->net->p.prefixlen; + p->u.prefix4 = pi->net->p.u.prefix4; + p->prefixlen = pi->net->p.prefixlen; } else { - p->u.prefix4 = ri->attr->nexthop; + p->u.prefix4 = pi->attr->nexthop; p->prefixlen = IPV4_MAX_BITLEN; } break; case AFI_IP6: - /* We don't register link local NH */ - if (ri->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL - || IN6_IS_ADDR_LINKLOCAL(&ri->attr->mp_nexthop_global)) - return -1; - p->family = AF_INET6; if (is_bgp_static) { - p->u.prefix6 = ri->net->p.u.prefix6; - p->prefixlen = ri->net->p.prefixlen; + p->u.prefix6 = pi->net->p.u.prefix6; + p->prefixlen = pi->net->p.prefixlen; } else { - p->u.prefix6 = ri->attr->mp_nexthop_global; + p->u.prefix6 = pi->attr->mp_nexthop_global; p->prefixlen = IPV6_MAX_BITLEN; } break; @@ -686,7 +672,7 @@ static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc, static void evaluate_paths(struct bgp_nexthop_cache *bnc) { struct bgp_node *rn; - struct bgp_info *path; + struct bgp_path_info *path; int afi; struct peer *peer = (struct peer *)bnc->nht_info; struct bgp_table *table; @@ -753,14 +739,16 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) (bnc_is_valid_nexthop ? "" : "not ")); } - if ((CHECK_FLAG(path->flags, BGP_INFO_VALID) ? 1 : 0) + if ((CHECK_FLAG(path->flags, BGP_PATH_VALID) ? 1 : 0) != bnc_is_valid_nexthop) { - if (CHECK_FLAG(path->flags, BGP_INFO_VALID)) { + if (CHECK_FLAG(path->flags, BGP_PATH_VALID)) { bgp_aggregate_decrement(bgp_path, &rn->p, path, afi, safi); - bgp_info_unset_flag(rn, path, BGP_INFO_VALID); + bgp_path_info_unset_flag(rn, path, + BGP_PATH_VALID); } else { - bgp_info_set_flag(rn, path, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, path, + BGP_PATH_VALID); bgp_aggregate_increment(bgp_path, &rn->p, path, afi, safi); } @@ -769,13 +757,14 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) /* Copy the metric to the path. Will be used for bestpath * computation */ if (bgp_isvalid_nexthop(bnc) && bnc->metric) - (bgp_info_extra_get(path))->igpmetric = bnc->metric; + (bgp_path_info_extra_get(path))->igpmetric = + bnc->metric; else if (path->extra) path->extra->igpmetric = 0; if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED) || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) - SET_FLAG(path->flags, BGP_INFO_IGP_CHANGED); + SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED); bgp_process(bgp_path, rn, afi, safi); } @@ -799,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_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 a821a42c20..0cc045a065 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -32,7 +32,7 @@ extern void bgp_parse_nexthop_update(int command, vrf_id_t vrf_id); * p - path for which the nexthop object is being looked up * connected - True if NH MUST be a connected route */ -extern int bgp_find_nexthop(struct bgp_info *p, int connected); +extern int bgp_find_nexthop(struct bgp_path_info *p, int connected); /** * bgp_find_or_add_nexthop() - lookup the nexthop cache table for the bnc @@ -47,16 +47,17 @@ extern int bgp_find_nexthop(struct bgp_info *p, int connected); * connected - True if NH MUST be a connected route */ extern int bgp_find_or_add_nexthop(struct bgp *bgp_route, - struct bgp *bgp_nexthop, afi_t a, struct bgp_info *p, - struct peer *peer, int connected); + struct bgp *bgp_nexthop, afi_t a, + struct bgp_path_info *p, struct peer *peer, + int connected); /** * bgp_unlink_nexthop() - Unlink the nexthop object from the path structure. * ARGUMENTS: * p - path structure. */ -extern void bgp_unlink_nexthop(struct bgp_info *p); -void bgp_unlink_nexthop_by_peer(struct peer *); +extern void bgp_unlink_nexthop(struct bgp_path_info *p); +void bgp_unlink_nexthop_by_peer(struct peer *peer); /** * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected @@ -74,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_packet.c b/bgpd/bgp_packet.c index 96f3c8324f..73a07c8232 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -272,7 +272,7 @@ static void bgp_update_explicit_eors(struct peer *peer) PEER_STATUS_EOR_RECEIVED)) { if (bgp_debug_neighbor_events(peer)) zlog_debug( - " afi %d safi %d didnt receive EOR", + " afi %d safi %d didn't receive EOR", afi, safi); return; } diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index a74b584e90..edd8317c31 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -227,7 +227,7 @@ struct bgp_pbr_or_filter { }; static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, - struct bgp_info *binfo, + struct bgp_path_info *path, struct bgp_pbr_filter *bpf, struct nexthop *nh, float *rate); @@ -627,7 +627,7 @@ static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api) /* return -1 if build or validation failed */ static int bgp_pbr_build_and_validate_entry(struct prefix *p, - struct bgp_info *info, + struct bgp_path_info *path, struct bgp_pbr_entry_main *api) { int ret; @@ -645,8 +645,8 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p, if (ret < 0) return -1; /* extract actiosn from flowspec ecom list */ - if (info && info->attr && info->attr->ecommunity) { - ecom = info->attr->ecommunity; + if (path && path->attr && path->attr->ecommunity) { + ecom = path->attr->ecommunity; for (i = 0; i < ecom->size; i++) { ecom_eval = (struct ecommunity_val *) (ecom->val + (i * ECOMMUNITY_SIZE)); @@ -690,7 +690,7 @@ static int bgp_pbr_build_and_validate_entry(struct prefix *p, (char)ECOMMUNITY_REDIRECT_IP_NH)) { api_action->action = ACTION_REDIRECT_IP; api_action->u.zr.redirect_ip_v4.s_addr = - info->attr->nexthop.s_addr; + path->attr->nexthop.s_addr; api_action->u.zr.duplicate = ecom_eval->val[7]; } else { if (ecom_eval->val[0] != @@ -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, @@ -1223,16 +1220,16 @@ static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa, bgp_send_pbr_ipset_entry_match(bpme, false); bpme->installed = false; bpme->backpointer = NULL; - if (bpme->bgp_info) { - struct bgp_info *bgp_info; - struct bgp_info_extra *extra; + if (bpme->path) { + struct bgp_path_info *path; + struct bgp_path_info_extra *extra; - /* unlink bgp_info to bpme */ - bgp_info = (struct bgp_info *)bpme->bgp_info; - extra = bgp_info_extra_get(bgp_info); + /* unlink bgp_path_info to bpme */ + path = (struct bgp_path_info *)bpme->path; + extra = bgp_path_info_extra_get(path); if (extra->bgp_fs_pbr) listnode_delete(extra->bgp_fs_pbr, bpme); - bpme->bgp_info = NULL; + bpme->path = NULL; } } hash_release(bpm->entry_hash, bpme); @@ -1304,9 +1301,8 @@ static int bgp_pbr_get_remaining_entry(struct hash_backet *backet, void *arg) return HASHWALK_ABORT; } -static void bgp_pbr_policyroute_remove_from_zebra_unit(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf) +static void bgp_pbr_policyroute_remove_from_zebra_unit( + struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf) { struct bgp_pbr_match temp; struct bgp_pbr_match_entry temp2; @@ -1438,13 +1434,10 @@ static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry) return 0; } -static void bgp_pbr_icmp_action(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct bgp_pbr_or_filter *bpof, - bool add, - struct nexthop *nh, - float *rate) +static void bgp_pbr_icmp_action(struct bgp *bgp, struct bgp_path_info *path, + struct bgp_pbr_filter *bpf, + struct bgp_pbr_or_filter *bpof, bool add, + struct nexthop *nh, float *rate) { struct bgp_pbr_range_port srcp, dstp; struct bgp_pbr_val_mask *icmp_type, *icmp_code; @@ -1466,11 +1459,11 @@ static void bgp_pbr_icmp_action(struct bgp *bgp, for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) { dstp.min_port = icmp_code->val; if (add) - bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, - bpf, nh, rate); + bgp_pbr_policyroute_add_to_zebra_unit( + bgp, path, bpf, nh, rate); else bgp_pbr_policyroute_remove_from_zebra_unit( - bgp, binfo, bpf); + bgp, path, bpf); } return; } @@ -1487,31 +1480,27 @@ static void bgp_pbr_icmp_action(struct bgp *bgp, dstp.max_port = 255; if (add) bgp_pbr_policyroute_add_to_zebra_unit( - bgp, binfo, - bpf, nh, rate); + bgp, path, bpf, nh, rate); else - bgp_pbr_policyroute_remove_from_zebra_unit(bgp, - binfo, bpf); + bgp_pbr_policyroute_remove_from_zebra_unit( + bgp, path, bpf); continue; } for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) { dstp.min_port = icmp_code->val; if (add) bgp_pbr_policyroute_add_to_zebra_unit( - bgp, binfo, - bpf, nh, rate); + bgp, path, bpf, nh, rate); else bgp_pbr_policyroute_remove_from_zebra_unit( - bgp, binfo, bpf); + bgp, path, bpf); } } } -static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct bgp_pbr_or_filter *bpof, - uint8_t type_entry) +static void bgp_pbr_policyroute_remove_from_zebra_recursive( + struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf, + struct bgp_pbr_or_filter *bpof, uint8_t type_entry) { struct listnode *node, *nnode; struct bgp_pbr_val_mask *valmask; @@ -1520,8 +1509,8 @@ static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp, struct bgp_pbr_val_mask **target_val; if (type_entry == 0) - return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, - binfo, bpf); + return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, + bpf); next_type_entry = bgp_pbr_next_type_entry(type_entry); if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) { orig_list = bpof->tcpflags; @@ -1538,53 +1527,43 @@ static void bgp_pbr_policyroute_remove_from_zebra_recursive(struct bgp *bgp, } else if (type_entry == FLOWSPEC_ICMP_TYPE && (bpof->icmp_type || bpof->icmp_code)) { /* enumerate list for icmp - must be last one */ - bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, false, NULL, NULL); + bgp_pbr_icmp_action(bgp, path, bpf, bpof, false, NULL, NULL); return; } else { - return bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, - binfo, - bpf, bpof, - next_type_entry); + return bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, next_type_entry); } for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) { *target_val = valmask; - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - next_type_entry); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, next_type_entry); } } -static void bgp_pbr_policyroute_remove_from_zebra(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct bgp_pbr_or_filter *bpof) +static void bgp_pbr_policyroute_remove_from_zebra( + struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf, + struct bgp_pbr_or_filter *bpof) { if (!bpof) - return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, - binfo, + return bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf); if (bpof->tcpflags) - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - FLOWSPEC_TCP_FLAGS); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, FLOWSPEC_TCP_FLAGS); else if (bpof->dscp) - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - FLOWSPEC_DSCP); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, FLOWSPEC_DSCP); else if (bpof->pkt_len) - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - FLOWSPEC_PKT_LEN); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, FLOWSPEC_PKT_LEN); else if (bpof->fragment) - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - FLOWSPEC_FRAGMENT); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, FLOWSPEC_FRAGMENT); else if (bpof->icmp_type || bpof->icmp_code) - bgp_pbr_policyroute_remove_from_zebra_recursive(bgp, binfo, - bpf, bpof, - FLOWSPEC_ICMP_TYPE); + bgp_pbr_policyroute_remove_from_zebra_recursive( + bgp, path, bpf, bpof, FLOWSPEC_ICMP_TYPE); else - bgp_pbr_policyroute_remove_from_zebra_unit(bgp, binfo, bpf); + bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf); /* flush bpof */ if (bpof->tcpflags) list_delete_all_node(bpof->tcpflags); @@ -1692,10 +1671,10 @@ static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add) } static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct nexthop *nh, - float *rate) + struct bgp_path_info *path, + struct bgp_pbr_filter *bpf, + struct nexthop *nh, + float *rate) { struct bgp_pbr_match temp; struct bgp_pbr_match_entry temp2; @@ -1848,19 +1827,21 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, bpme->installed = false; bpme->install_in_progress = false; /* link bgp info to bpme */ - bpme->bgp_info = (void *)binfo; + bpme->path = (void *)path; } else bpme_found = true; /* already installed */ if (bpme_found) { - struct bgp_info_extra *extra = bgp_info_extra_get(binfo); + struct bgp_path_info_extra *extra = + bgp_path_info_extra_get(path); if (extra && extra->bgp_fs_pbr && listnode_lookup(extra->bgp_fs_pbr, bpme)) { if (BGP_DEBUG(pbr, PBR_ERROR)) - zlog_err("%s: entry %p/%p already installed in bgp pbr", - __func__, binfo, bpme); + zlog_err( + "%s: entry %p/%p already installed in bgp pbr", + __func__, path, bpme); return; } } @@ -1911,13 +1892,10 @@ static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp, } -static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct bgp_pbr_or_filter *bpof, - struct nexthop *nh, - float *rate, - uint8_t type_entry) +static void bgp_pbr_policyroute_add_to_zebra_recursive( + struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf, + struct bgp_pbr_or_filter *bpof, struct nexthop *nh, float *rate, + uint8_t type_entry) { struct listnode *node, *nnode; struct bgp_pbr_val_mask *valmask; @@ -1926,8 +1904,8 @@ static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp, struct bgp_pbr_val_mask **target_val; if (type_entry == 0) - return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf, - nh, rate); + return bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, + rate); next_type_entry = bgp_pbr_next_type_entry(type_entry); if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) { orig_list = bpof->tcpflags; @@ -1944,59 +1922,45 @@ static void bgp_pbr_policyroute_add_to_zebra_recursive(struct bgp *bgp, } else if (type_entry == FLOWSPEC_ICMP_TYPE && (bpof->icmp_type || bpof->icmp_code)) { /* enumerate list for icmp - must be last one */ - bgp_pbr_icmp_action(bgp, binfo, bpf, bpof, true, nh, rate); + bgp_pbr_icmp_action(bgp, path, bpf, bpof, true, nh, rate); return; } else { - return bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, nh, rate, - next_type_entry); + return bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, next_type_entry); } for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) { *target_val = valmask; - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, - nh, rate, - next_type_entry); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, next_type_entry); } } static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_filter *bpf, - struct bgp_pbr_or_filter *bpof, - struct nexthop *nh, - float *rate) + struct bgp_path_info *path, + struct bgp_pbr_filter *bpf, + struct bgp_pbr_or_filter *bpof, + struct nexthop *nh, float *rate) { if (!bpof) - return bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, - bpf, nh, rate); + return bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, + rate); if (bpof->tcpflags) - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, - nh, rate, - FLOWSPEC_TCP_FLAGS); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, FLOWSPEC_TCP_FLAGS); else if (bpof->dscp) - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, - nh, rate, - FLOWSPEC_DSCP); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, FLOWSPEC_DSCP); else if (bpof->pkt_len) - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, - nh, rate, - FLOWSPEC_PKT_LEN); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, FLOWSPEC_PKT_LEN); else if (bpof->fragment) - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, - nh, rate, - FLOWSPEC_FRAGMENT); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, FLOWSPEC_FRAGMENT); else if (bpof->icmp_type || bpof->icmp_code) - bgp_pbr_policyroute_add_to_zebra_recursive(bgp, binfo, - bpf, bpof, nh, rate, - FLOWSPEC_ICMP_TYPE); + bgp_pbr_policyroute_add_to_zebra_recursive( + bgp, path, bpf, bpof, nh, rate, FLOWSPEC_ICMP_TYPE); else - bgp_pbr_policyroute_add_to_zebra_unit(bgp, binfo, bpf, - nh, rate); + bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate); /* flush bpof */ if (bpof->tcpflags) list_delete_all_node(bpof->tcpflags); @@ -2012,10 +1976,8 @@ static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp, list_delete_all_node(bpof->icmp_code); } -static void bgp_pbr_handle_entry(struct bgp *bgp, - struct bgp_info *binfo, - struct bgp_pbr_entry_main *api, - bool add) +static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path, + struct bgp_pbr_entry_main *api, bool add) { struct nexthop nh; int i = 0; @@ -2151,9 +2113,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, bpf.src_port = srcp; bpf.dst_port = dstp; if (!add) - return bgp_pbr_policyroute_remove_from_zebra(bgp, - binfo, - &bpf, &bpof); + return bgp_pbr_policyroute_remove_from_zebra(bgp, path, &bpf, + &bpof); /* no action for add = true */ for (i = 0; i < api->action_num; i++) { switch (api->actions[i].action) { @@ -2162,9 +2123,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, if (api->actions[i].u.r.rate == 0) { nh.vrf_id = api->vrf_id; nh.type = NEXTHOP_TYPE_BLACKHOLE; - bgp_pbr_policyroute_add_to_zebra(bgp, binfo, - &bpf, &bpof, - &nh, &rate); + bgp_pbr_policyroute_add_to_zebra( + bgp, path, &bpf, &bpof, &nh, &rate); } else { /* update rate. can be reentrant */ rate = api->actions[i].u.r.rate; @@ -2204,8 +2164,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, nh.gate.ipv4.s_addr = api->actions[i].u.zr.redirect_ip_v4.s_addr; nh.vrf_id = api->vrf_id; - bgp_pbr_policyroute_add_to_zebra(bgp, binfo, - &bpf, &bpof, + bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof, &nh, &rate); /* XXX combination with REDIRECT_VRF * + REDIRECT_NH_IP not done @@ -2215,8 +2174,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, case ACTION_REDIRECT: nh.vrf_id = api->actions[i].u.redirect_vrf; nh.type = NEXTHOP_TYPE_IPV4; - bgp_pbr_policyroute_add_to_zebra(bgp, binfo, - &bpf, &bpof, + bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof, &nh, &rate); continue_loop = 0; break; @@ -2236,8 +2194,8 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, } void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, - struct bgp_info *info, afi_t afi, safi_t safi, - bool nlri_update) + struct bgp_path_info *info, afi_t afi, safi_t safi, + bool nlri_update) { struct bgp_pbr_entry_main api; diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index e853784afd..84095f9ab9 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -219,7 +219,7 @@ struct bgp_pbr_match_entry { uint16_t dst_port_max; uint8_t proto; - void *bgp_info; + void *path; bool installed; bool install_in_progress; @@ -267,23 +267,22 @@ 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); struct bgp_node; -struct bgp_info; +struct bgp_path_info; extern void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p, - struct bgp_info *new_select, - afi_t afi, safi_t safi, - bool nlri_update); + struct bgp_path_info *new_select, afi_t afi, + safi_t safi, bool nlri_update); /* bgp pbr utilities */ extern struct bgp_pbr_interface *pbr_interface_lookup(const char *name); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 815a40190b..a407ffba41 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -164,19 +164,20 @@ struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, return rn; } -/* Allocate bgp_info_extra */ -static struct bgp_info_extra *bgp_info_extra_new(void) +/* Allocate bgp_path_info_extra */ +static struct bgp_path_info_extra *bgp_path_info_extra_new(void) { - struct bgp_info_extra *new; - new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, sizeof(struct bgp_info_extra)); + struct bgp_path_info_extra *new; + new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA, + sizeof(struct bgp_path_info_extra)); new->label[0] = MPLS_INVALID_LABEL; new->num_labels = 0; return new; } -static void bgp_info_extra_free(struct bgp_info_extra **extra) +static void bgp_path_info_extra_free(struct bgp_path_info_extra **extra) { - struct bgp_info_extra *e; + struct bgp_path_info_extra *e; if (!extra || !*extra) return; @@ -187,27 +188,27 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) e->damp_info = NULL; if (e->parent) { - struct bgp_info *bi = (struct bgp_info *)e->parent; + struct bgp_path_info *bpi = (struct bgp_path_info *)e->parent; - if (bi->net) { + if (bpi->net) { /* FIXME: since multiple e may have the same e->parent * and e->parent->net is holding a refcount for each * of them, we need to do some fudging here. * - * WARNING: if bi->net->lock drops to 0, bi may be - * freed as well (because bi->net was holding the - * last reference to bi) => write after free! + * WARNING: if bpi->net->lock drops to 0, bpi may be + * freed as well (because bpi->net was holding the + * last reference to bpi) => write after free! */ unsigned refcount; - bi = bgp_info_lock(bi); - refcount = bi->net->lock - 1; - bgp_unlock_node((struct bgp_node *)bi->net); + bpi = bgp_path_info_lock(bpi); + refcount = bpi->net->lock - 1; + bgp_unlock_node((struct bgp_node *)bpi->net); if (!refcount) - bi->net = NULL; - bgp_info_unlock(bi); + bpi->net = NULL; + bgp_path_info_unlock(bpi); } - bgp_info_unlock(e->parent); + bgp_path_info_unlock(e->parent); e->parent = NULL; } @@ -221,182 +222,184 @@ static void bgp_info_extra_free(struct bgp_info_extra **extra) *extra = NULL; } -/* Get bgp_info extra information for the given bgp_info, lazy allocated - * if required. +/* Get bgp_path_info extra information for the given bgp_path_info, lazy + * allocated if required. */ -struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *ri) +struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi) { - if (!ri->extra) - ri->extra = bgp_info_extra_new(); - return ri->extra; + if (!pi->extra) + pi->extra = bgp_path_info_extra_new(); + return pi->extra; } /* Allocate new bgp info structure. */ -struct bgp_info *bgp_info_new(void) +struct bgp_path_info *bgp_path_info_new(void) { - return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info)); + return XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info)); } /* Free bgp route information. */ -static void bgp_info_free(struct bgp_info *binfo) +static void bgp_path_info_free(struct bgp_path_info *path) { - if (binfo->attr) - bgp_attr_unintern(&binfo->attr); + if (path->attr) + bgp_attr_unintern(&path->attr); - bgp_unlink_nexthop(binfo); - bgp_info_extra_free(&binfo->extra); - bgp_info_mpath_free(&binfo->mpath); + bgp_unlink_nexthop(path); + bgp_path_info_extra_free(&path->extra); + bgp_path_info_mpath_free(&path->mpath); - peer_unlock(binfo->peer); /* bgp_info peer reference */ + peer_unlock(path->peer); /* bgp_path_info peer reference */ - XFREE(MTYPE_BGP_ROUTE, binfo); + XFREE(MTYPE_BGP_ROUTE, path); } -struct bgp_info *bgp_info_lock(struct bgp_info *binfo) +struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path) { - binfo->lock++; - return binfo; + path->lock++; + return path; } -struct bgp_info *bgp_info_unlock(struct bgp_info *binfo) +struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path) { - assert(binfo && binfo->lock > 0); - binfo->lock--; + assert(path && path->lock > 0); + path->lock--; - if (binfo->lock == 0) { + if (path->lock == 0) { #if 0 zlog_debug ("%s: unlocked and freeing", __func__); zlog_backtrace (LOG_DEBUG); #endif - bgp_info_free(binfo); + bgp_path_info_free(path); return NULL; } #if 0 - if (binfo->lock == 1) + if (path->lock == 1) { zlog_debug ("%s: unlocked to 1", __func__); zlog_backtrace (LOG_DEBUG); } #endif - return binfo; + return path; } -void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri) +void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi) { - struct bgp_info *top; + struct bgp_path_info *top; top = rn->info; - ri->next = rn->info; - ri->prev = NULL; + pi->next = rn->info; + pi->prev = NULL; if (top) - top->prev = ri; - rn->info = ri; + top->prev = pi; + rn->info = pi; - bgp_info_lock(ri); + bgp_path_info_lock(pi); bgp_lock_node(rn); - peer_lock(ri->peer); /* bgp_info peer reference */ + peer_lock(pi->peer); /* bgp_path_info peer reference */ } /* Do the actual removal of info from RIB, for use by bgp_process completion callback *only* */ -void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri) +void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi) { - if (ri->next) - ri->next->prev = ri->prev; - if (ri->prev) - ri->prev->next = ri->next; + if (pi->next) + pi->next->prev = pi->prev; + if (pi->prev) + pi->prev->next = pi->next; else - rn->info = ri->next; + rn->info = pi->next; - bgp_info_mpath_dequeue(ri); - bgp_info_unlock(ri); + bgp_path_info_mpath_dequeue(pi); + bgp_path_info_unlock(pi); bgp_unlock_node(rn); } -void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri) +void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi) { - bgp_info_set_flag(rn, ri, BGP_INFO_REMOVED); + bgp_path_info_set_flag(rn, pi, BGP_PATH_REMOVED); /* set of previous already took care of pcount */ - UNSET_FLAG(ri->flags, BGP_INFO_VALID); + UNSET_FLAG(pi->flags, BGP_PATH_VALID); } -/* undo the effects of a previous call to bgp_info_delete; typically +/* undo the effects of a previous call to bgp_path_info_delete; typically called when a route is deleted and then quickly re-added before the deletion has been processed */ -void bgp_info_restore(struct bgp_node *rn, struct bgp_info *ri) +void bgp_path_info_restore(struct bgp_node *rn, struct bgp_path_info *pi) { - bgp_info_unset_flag(rn, ri, BGP_INFO_REMOVED); + bgp_path_info_unset_flag(rn, pi, BGP_PATH_REMOVED); /* unset of previous already took care of pcount */ - SET_FLAG(ri->flags, BGP_INFO_VALID); + SET_FLAG(pi->flags, BGP_PATH_VALID); } /* Adjust pcount as required */ -static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_info *ri) +static void bgp_pcount_adjust(struct bgp_node *rn, struct bgp_path_info *pi) { struct bgp_table *table; assert(rn && bgp_node_table(rn)); - assert(ri && ri->peer && ri->peer->bgp); + assert(pi && pi->peer && pi->peer->bgp); table = bgp_node_table(rn); - if (ri->peer == ri->peer->bgp->peer_self) + if (pi->peer == pi->peer->bgp->peer_self) return; - if (!BGP_INFO_COUNTABLE(ri) - && CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + if (!BGP_PATH_COUNTABLE(pi) + && CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { - UNSET_FLAG(ri->flags, BGP_INFO_COUNTED); + UNSET_FLAG(pi->flags, BGP_PATH_COUNTED); /* slight hack, but more robust against errors. */ - if (ri->peer->pcount[table->afi][table->safi]) - ri->peer->pcount[table->afi][table->safi]--; + if (pi->peer->pcount[table->afi][table->safi]) + pi->peer->pcount[table->afi][table->safi]--; else flog_err(EC_LIB_DEVELOPMENT, "Asked to decrement 0 prefix count for peer"); - } else if (BGP_INFO_COUNTABLE(ri) - && !CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { - SET_FLAG(ri->flags, BGP_INFO_COUNTED); - ri->peer->pcount[table->afi][table->safi]++; + } else if (BGP_PATH_COUNTABLE(pi) + && !CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { + SET_FLAG(pi->flags, BGP_PATH_COUNTED); + pi->peer->pcount[table->afi][table->safi]++; } } -static int bgp_label_index_differs(struct bgp_info *ri1, struct bgp_info *ri2) +static int bgp_label_index_differs(struct bgp_path_info *pi1, + struct bgp_path_info *pi2) { - return (!(ri1->attr->label_index == ri2->attr->label_index)); + return (!(pi1->attr->label_index == pi2->attr->label_index)); } -/* Set/unset bgp_info flags, adjusting any other state as needed. +/* Set/unset bgp_path_info flags, adjusting any other state as needed. * This is here primarily to keep prefix-count in check. */ -void bgp_info_set_flag(struct bgp_node *rn, struct bgp_info *ri, uint32_t flag) +void bgp_path_info_set_flag(struct bgp_node *rn, struct bgp_path_info *pi, + uint32_t flag) { - SET_FLAG(ri->flags, flag); + SET_FLAG(pi->flags, flag); /* early bath if we know it's not a flag that changes countability state */ if (!CHECK_FLAG(flag, - BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) + BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED)) return; - bgp_pcount_adjust(rn, ri); + bgp_pcount_adjust(rn, pi); } -void bgp_info_unset_flag(struct bgp_node *rn, struct bgp_info *ri, - uint32_t flag) +void bgp_path_info_unset_flag(struct bgp_node *rn, struct bgp_path_info *pi, + uint32_t flag) { - UNSET_FLAG(ri->flags, flag); + UNSET_FLAG(pi->flags, flag); /* early bath if we know it's not a flag that changes countability state */ if (!CHECK_FLAG(flag, - BGP_INFO_VALID | BGP_INFO_HISTORY | BGP_INFO_REMOVED)) + BGP_PATH_VALID | BGP_PATH_HISTORY | BGP_PATH_REMOVED)) return; - bgp_pcount_adjust(rn, ri); + bgp_pcount_adjust(rn, pi); } /* Get MED value. If MED value is missing and "bgp bestpath @@ -413,21 +416,21 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp) } } -void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf) +void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf) { - if (ri->addpath_rx_id) - sprintf(buf, "path %s (addpath rxid %d)", ri->peer->host, - ri->addpath_rx_id); + if (pi->addpath_rx_id) + sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host, + pi->addpath_rx_id); else - sprintf(buf, "path %s", ri->peer->host); + sprintf(buf, "path %s", pi->peer->host); } /* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1. */ -static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, - struct bgp_info *exist, int *paths_eq, - struct bgp_maxpaths_cfg *mpath_cfg, int debug, - char *pfx_buf, afi_t afi, safi_t safi) +static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, + struct bgp_path_info *exist, int *paths_eq, + struct bgp_maxpaths_cfg *mpath_cfg, int debug, + char *pfx_buf, afi_t afi, safi_t safi) { struct attr *newattr, *existattr; bgp_peer_sort_t new_sort; @@ -461,7 +464,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, } if (debug) - bgp_info_path_with_addpath_rx_str(new, new_buf); + bgp_path_info_path_with_addpath_rx_str(new, new_buf); if (exist == NULL) { if (debug) @@ -471,7 +474,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, } if (debug) { - bgp_info_path_with_addpath_rx_str(exist, exist_buf); + bgp_path_info_path_with_addpath_rx_str(exist, exist_buf); zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x", pfx_buf, new_buf, new->flags, exist_buf, exist->flags); @@ -499,9 +502,10 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, prefix2str(&new->net->p, pfx_buf, sizeof(*pfx_buf) * PREFIX2STR_BUFFER); - bgp_info_path_with_addpath_rx_str(new, new_buf); - bgp_info_path_with_addpath_rx_str(exist, - exist_buf); + bgp_path_info_path_with_addpath_rx_str(new, + new_buf); + bgp_path_info_path_with_addpath_rx_str( + exist, exist_buf); } if (newattr->sticky && !existattr->sticky) { @@ -896,7 +900,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, preferred route based on the additional decision criteria below. */ if (!bgp_flag_check(bgp, BGP_FLAG_COMPARE_ROUTER_ID) && new_sort == BGP_PEER_EBGP && exist_sort == BGP_PEER_EBGP) { - if (CHECK_FLAG(new->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(new->flags, BGP_PATH_SELECTED)) { if (debug) zlog_debug( "%s: %s wins over %s due to oldest external", @@ -904,7 +908,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, return 1; } - if (CHECK_FLAG(exist->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(exist->flags, BGP_PATH_SELECTED)) { if (debug) zlog_debug( "%s: %s loses to %s due to oldest external", @@ -969,7 +973,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, /* Do this only if neither path is "stale" as stale paths do not have * valid peer information (as the connection may or may not be up). */ - if (CHECK_FLAG(exist->flags, BGP_INFO_STALE)) { + if (CHECK_FLAG(exist->flags, BGP_PATH_STALE)) { if (debug) zlog_debug( "%s: %s wins over %s due to latter path being STALE", @@ -977,7 +981,7 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, return 1; } - if (CHECK_FLAG(new->flags, BGP_INFO_STALE)) { + if (CHECK_FLAG(new->flags, BGP_PATH_STALE)) { if (debug) zlog_debug( "%s: %s loses to %s due to former path being STALE", @@ -1020,14 +1024,14 @@ static int bgp_info_cmp(struct bgp *bgp, struct bgp_info *new, * is preferred, or 0 if they are the same (usually will only occur if * multipath is enabled * This version is compatible with */ -int bgp_info_cmp_compatible(struct bgp *bgp, struct bgp_info *new, - struct bgp_info *exist, char *pfx_buf, afi_t afi, - safi_t safi) +int bgp_path_info_cmp_compatible(struct bgp *bgp, struct bgp_path_info *new, + struct bgp_path_info *exist, char *pfx_buf, + afi_t afi, safi_t safi) { int paths_eq; int ret; - ret = bgp_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, afi, - safi); + ret = bgp_path_info_cmp(bgp, new, exist, &paths_eq, NULL, 0, pfx_buf, + afi, safi); if (paths_eq) ret = 0; @@ -1164,7 +1168,7 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p, const char *rmap_name) { struct bgp_filter *filter; - struct bgp_info info; + struct bgp_path_info rmap_path; route_map_result_t ret; struct route_map *rmap = NULL; @@ -1190,15 +1194,15 @@ static int bgp_input_modifier(struct peer *peer, struct prefix *p, /* Route map apply. */ if (rmap) { - memset(&info, 0, sizeof(struct bgp_info)); + memset(&rmap_path, 0, sizeof(struct bgp_path_info)); /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + rmap_path.peer = peer; + rmap_path.attr = attr; SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN); /* Apply BGP route map to the attribute. */ - ret = route_map_apply(rmap, p, RMAP_BGP, &info); + ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path); peer->rmap_type = 0; @@ -1212,7 +1216,7 @@ static int bgp_output_modifier(struct peer *peer, struct prefix *p, struct attr *attr, afi_t afi, safi_t safi, const char *rmap_name) { - struct bgp_info info; + struct bgp_path_info rmap_path; route_map_result_t ret; struct route_map *rmap = NULL; uint8_t rmap_type; @@ -1239,17 +1243,17 @@ static int bgp_output_modifier(struct peer *peer, struct prefix *p, if (rmap == NULL) return RMAP_DENY; - memset(&info, 0, sizeof(struct bgp_info)); + memset(&rmap_path, 0, sizeof(struct bgp_path_info)); /* Route map apply. */ /* Duplicate current value to new strucutre for modification. */ - info.peer = peer; - info.attr = attr; + rmap_path.peer = peer; + rmap_path.attr = attr; rmap_type = peer->rmap_type; SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); /* Apply BGP route map to the attribute. */ - ret = route_map_apply(rmap, p, RMAP_BGP, &info); + ret = route_map_apply(rmap, p, RMAP_BGP, &rmap_path); peer->rmap_type = rmap_type; @@ -1341,15 +1345,15 @@ void bgp_attr_add_gshut_community(struct attr *attr) merge = community_merge(community_dup(old), gshut); if (old->refcnt == 0) - community_free(old); + community_free(&old); new = community_uniq_sort(merge); - community_free(merge); + community_free(&merge); } else { new = community_dup(gshut); } - community_free(gshut); + community_free(&gshut); attr->community = new; attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); @@ -1372,7 +1376,7 @@ static void subgroup_announce_reset_nhop(uint8_t family, struct attr *attr) memset(&attr->mp_nexthop_global_in, 0, BGP_ATTR_NHLEN_IPV4); } -int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, +int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, struct update_subgroup *subgrp, struct prefix *p, struct attr *attr) { @@ -1381,7 +1385,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer; struct peer *onlypeer; struct bgp *bgp; - struct attr *riattr; + struct attr *piattr; char buf[PREFIX_STRLEN]; int ret; int transparent; @@ -1400,15 +1404,16 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, if (CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL)) onlypeer = SUBGRP_PFIRST(subgrp)->peer; - from = ri->peer; + from = pi->peer; filter = &peer->filter[afi][safi]; bgp = SUBGRP_INST(subgrp); - riattr = bgp_info_mpath_count(ri) ? bgp_info_mpath_attr(ri) : ri->attr; + piattr = bgp_path_info_mpath_count(pi) ? bgp_path_info_mpath_attr(pi) + : pi->attr; #if ENABLE_BGP_VNC if (((afi == AFI_IP) || (afi == AFI_IP6)) && (safi == SAFI_MPLS_VPN) - && ((ri->type == ZEBRA_ROUTE_BGP_DIRECT) - || (ri->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { + && ((pi->type == ZEBRA_ROUTE_BGP_DIRECT) + || (pi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT))) { /* * direct and direct_ext type routes originate internally even @@ -1424,8 +1429,8 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, if (((afi == AFI_IP) || (afi == AFI_IP6)) && ((safi == SAFI_MPLS_VPN) || (safi == SAFI_UNICAST)) - && (ri->type == ZEBRA_ROUTE_BGP) - && (ri->sub_type == BGP_ROUTE_IMPORTED)) { + && (pi->type == ZEBRA_ROUTE_BGP) + && (pi->sub_type == BGP_ROUTE_IMPORTED)) { /* Applies to routes leaked vpn->vrf and vrf->vpn */ @@ -1433,24 +1438,24 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, } /* With addpath we may be asked to TX all kinds of paths so make sure - * ri is valid */ - if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID) - || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY) - || CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + * pi is valid */ + if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID) + || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY) + || CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { return 0; } /* If this is not the bestpath then check to see if there is an enabled * addpath * feature that requires us to advertise it */ - if (!CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { - if (!bgp_addpath_tx_path(peer, afi, safi, ri)) { + if (!CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { + if (!bgp_addpath_tx_path(peer, afi, safi, pi)) { return 0; } } /* Aggregate-address suppress check. */ - if (ri->extra && ri->extra->suppress) + if (pi->extra && pi->extra->suppress) if (!UNSUPPRESS_MAP_NAME(filter)) { return 0; } @@ -1461,13 +1466,13 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, * off box as that the RT and RD created are localy * significant and globaly useless. */ - if (safi == SAFI_MPLS_VPN && ri->extra && ri->extra->num_labels - && ri->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK) + if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels + && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK) return 0; /* If it's labeled safi, make sure the route has a valid label. */ if (safi == SAFI_LABELED_UNICAST) { - mpls_label_t label = bgp_adv_label(rn, ri, peer, afi, safi); + mpls_label_t label = bgp_adv_label(rn, pi, peer, afi, safi); if (!bgp_is_valid_label(&label)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug("u%" PRIu64 ":s%" PRIu64 @@ -1503,7 +1508,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, transparent = 0; /* If community is not disabled check the no-export and local. */ - if (!transparent && bgp_community_filter(peer, riattr)) { + if (!transparent && bgp_community_filter(peer, piattr)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "subgrpannouncecheck: community filter check fail"); @@ -1512,8 +1517,8 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, /* If the attribute has originator-id and it is same as remote peer's id. */ - if (onlypeer && riattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) - && (IPV4_ADDR_SAME(&onlypeer->remote_id, &riattr->originator_id))) { + if (onlypeer && piattr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID) + && (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "%s [Update:SEND] %s originator-id is same as " @@ -1543,7 +1548,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, } /* Output filter check. */ - if (bgp_output_filter(peer, p, riattr, afi, safi) == FILTER_DENY) { + if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug("%s [Update:SEND] %s is filtered", peer->host, prefix2str(p, buf, sizeof(buf))); @@ -1552,7 +1557,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, #ifdef BGP_SEND_ASPATH_CHECK /* AS path loop check. */ - if (onlypeer && aspath_loop_check(riattr->aspath, onlypeer->as)) { + if (onlypeer && aspath_loop_check(piattr->aspath, onlypeer->as)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "%s [Update:SEND] suppress announcement to peer AS %u " @@ -1564,7 +1569,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, /* If we're a CONFED we need to loop check the CONFED ID too */ if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { - if (aspath_loop_check(riattr->aspath, bgp->confed_id)) { + if (aspath_loop_check(piattr->aspath, bgp->confed_id)) { if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( "%s [Update:SEND] suppress announcement to peer AS %u" @@ -1604,7 +1609,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, } /* For modify attribute, copy it to temporary structure. */ - bgp_attr_dup(attr, riattr); + bgp_attr_dup(attr, piattr); /* If local-preference is not set. */ if ((peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED) @@ -1694,19 +1699,19 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, bgp_peer_as_override(bgp, afi, safi, peer, attr); /* Route map & unsuppress-map apply. */ - if (ROUTE_MAP_OUT_NAME(filter) || (ri->extra && ri->extra->suppress)) { - struct bgp_info info; - struct bgp_info_extra dummy_info_extra; + if (ROUTE_MAP_OUT_NAME(filter) || (pi->extra && pi->extra->suppress)) { + struct bgp_path_info rmap_path; + struct bgp_path_info_extra dummy_rmap_path_extra; struct attr dummy_attr; - memset(&info, 0, sizeof(struct bgp_info)); - info.peer = peer; - info.attr = attr; + memset(&rmap_path, 0, sizeof(struct bgp_path_info)); + rmap_path.peer = peer; + rmap_path.attr = attr; - if (ri->extra) { - memcpy(&dummy_info_extra, ri->extra, - sizeof(struct bgp_info_extra)); - info.extra = &dummy_info_extra; + if (pi->extra) { + memcpy(&dummy_rmap_path_extra, pi->extra, + sizeof(struct bgp_path_info_extra)); + rmap_path.extra = &dummy_rmap_path_extra; } /* don't confuse inbound and outbound setting */ @@ -1720,17 +1725,17 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, && !bgp_flag_check(bgp, BGP_FLAG_RR_ALLOW_OUTBOUND_POLICY)) { bgp_attr_dup(&dummy_attr, attr); - info.attr = &dummy_attr; + rmap_path.attr = &dummy_attr; } SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT); - if (ri->extra && ri->extra->suppress) + if (pi->extra && pi->extra->suppress) ret = route_map_apply(UNSUPPRESS_MAP(filter), p, - RMAP_BGP, &info); + RMAP_BGP, &rmap_path); else ret = route_map_apply(ROUTE_MAP_OUT(filter), p, - RMAP_BGP, &info); + RMAP_BGP, &rmap_path); peer->rmap_type = 0; @@ -1769,7 +1774,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, * it is configured as 'peer-address'. */ if (!bgp_rmap_nhop_changed(attr->rmap_change_flags, - riattr->rmap_change_flags) + piattr->rmap_change_flags) && !transparent && !CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_NEXTHOP_UNCHANGED)) { @@ -1794,14 +1799,14 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, * Note: 3rd party nexthop currently implemented for * IPv4 only. */ - if (!bgp_subgrp_multiaccess_check_v4(riattr->nexthop, + if (!bgp_subgrp_multiaccess_check_v4(piattr->nexthop, subgrp)) subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), attr); - } else if (CHECK_FLAG(ri->flags, BGP_INFO_ANNC_NH_SELF)) { + } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) { /* * This flag is used for leaked vpn-vrf routes */ @@ -1812,7 +1817,7 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, if (bgp_debug_update(NULL, p, subgrp->update_group, 0)) zlog_debug( - "%s: BGP_INFO_ANNC_NH_SELF, family=%s", + "%s: BGP_PATH_ANNC_NH_SELF, family=%s", __func__, family2str(family)); subgroup_announce_reset_nhop(family, attr); } @@ -1836,14 +1841,15 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_info_pair *result, afi_t afi, safi_t safi) + struct bgp_path_info_pair *result, afi_t afi, + safi_t safi) { - struct bgp_info *new_select; - struct bgp_info *old_select; - struct bgp_info *ri; - struct bgp_info *ri1; - struct bgp_info *ri2; - struct bgp_info *nextri = NULL; + struct bgp_path_info *new_select; + struct bgp_path_info *old_select; + struct bgp_path_info *pi; + struct bgp_path_info *pi1; + struct bgp_path_info *pi2; + struct bgp_path_info *nextpi = NULL; int paths_eq, do_mpath, debug; struct list mp_list; char pfx_buf[PREFIX2STR_BUFFER]; @@ -1862,66 +1868,66 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, new_select = NULL; if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED)) { - /* Clear BGP_INFO_DMED_SELECTED for all paths */ - for (ri1 = rn->info; ri1; ri1 = ri1->next) - bgp_info_unset_flag(rn, ri1, BGP_INFO_DMED_SELECTED); + /* Clear BGP_PATH_DMED_SELECTED for all paths */ + for (pi1 = rn->info; pi1; pi1 = pi1->next) + bgp_path_info_unset_flag(rn, pi1, + BGP_PATH_DMED_SELECTED); - for (ri1 = rn->info; ri1; ri1 = ri1->next) { - if (CHECK_FLAG(ri1->flags, BGP_INFO_DMED_CHECK)) + for (pi1 = rn->info; pi1; pi1 = pi1->next) { + if (CHECK_FLAG(pi1->flags, BGP_PATH_DMED_CHECK)) continue; - if (BGP_INFO_HOLDDOWN(ri1)) + if (BGP_PATH_HOLDDOWN(pi1)) continue; - if (ri1->peer && ri1->peer != bgp->peer_self) - if (ri1->peer->status != Established) + if (pi1->peer && pi1->peer != bgp->peer_self) + if (pi1->peer->status != Established) continue; - new_select = ri1; - if (ri1->next) { - for (ri2 = ri1->next; ri2; ri2 = ri2->next) { - if (CHECK_FLAG(ri2->flags, - BGP_INFO_DMED_CHECK)) + new_select = pi1; + if (pi1->next) { + for (pi2 = pi1->next; pi2; pi2 = pi2->next) { + if (CHECK_FLAG(pi2->flags, + BGP_PATH_DMED_CHECK)) continue; - if (BGP_INFO_HOLDDOWN(ri2)) + if (BGP_PATH_HOLDDOWN(pi2)) continue; - if (ri2->peer - && ri2->peer != bgp->peer_self + if (pi2->peer + && pi2->peer != bgp->peer_self && !CHECK_FLAG( - ri2->peer->sflags, + pi2->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri2->peer->status + if (pi2->peer->status != Established) continue; - if (aspath_cmp_left(ri1->attr->aspath, - ri2->attr->aspath) - || aspath_cmp_left_confed( - ri1->attr->aspath, - ri2->attr->aspath)) { - if (bgp_info_cmp(bgp, ri2, - new_select, - &paths_eq, - mpath_cfg, - debug, pfx_buf, - afi, safi)) { - bgp_info_unset_flag( - rn, new_select, - BGP_INFO_DMED_SELECTED); - new_select = ri2; - } + if (!aspath_cmp_left(pi1->attr->aspath, + pi2->attr->aspath) + && !aspath_cmp_left_confed( + pi1->attr->aspath, + pi2->attr->aspath)) + continue; - bgp_info_set_flag( - rn, ri2, - BGP_INFO_DMED_CHECK); + if (bgp_path_info_cmp( + bgp, pi2, new_select, + &paths_eq, mpath_cfg, debug, + pfx_buf, afi, safi)) { + bgp_path_info_unset_flag( + rn, new_select, + BGP_PATH_DMED_SELECTED); + new_select = pi2; } + + bgp_path_info_set_flag( + rn, pi2, BGP_PATH_DMED_CHECK); } } - bgp_info_set_flag(rn, new_select, BGP_INFO_DMED_CHECK); - bgp_info_set_flag(rn, new_select, - BGP_INFO_DMED_SELECTED); + bgp_path_info_set_flag(rn, new_select, + BGP_PATH_DMED_CHECK); + bgp_path_info_set_flag(rn, new_select, + BGP_PATH_DMED_SELECTED); if (debug) { - bgp_info_path_with_addpath_rx_str(new_select, - path_buf); + bgp_path_info_path_with_addpath_rx_str( + new_select, path_buf); zlog_debug("%s: %s is the bestpath from AS %u", pfx_buf, path_buf, aspath_get_first_as( @@ -1933,51 +1939,51 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, /* Check old selected route and new selected route. */ old_select = NULL; new_select = NULL; - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); - ri = nextri) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) - old_select = ri; + for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); + pi = nextpi) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) + old_select = pi; - if (BGP_INFO_HOLDDOWN(ri)) { + if (BGP_PATH_HOLDDOWN(pi)) { /* reap REMOVED routes, if needs be * selected route must stay for a while longer though */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) - && (ri != old_select)) - bgp_info_reap(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) + && (pi != old_select)) + bgp_path_info_reap(rn, pi); if (debug) - zlog_debug("%s: ri %p in holddown", __func__, - ri); + zlog_debug("%s: pi %p in holddown", __func__, + pi); continue; } - if (ri->peer && ri->peer != bgp->peer_self - && !CHECK_FLAG(ri->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri->peer->status != Established) { + if (pi->peer && pi->peer != bgp->peer_self + && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT)) + if (pi->peer->status != Established) { if (debug) zlog_debug( - "%s: ri %p non self peer %s not estab state", - __func__, ri, ri->peer->host); + "%s: pi %p non self peer %s not estab state", + __func__, pi, pi->peer->host); continue; } if (bgp_flag_check(bgp, BGP_FLAG_DETERMINISTIC_MED) - && (!CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED))) { - bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); + && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) { + bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK); if (debug) - zlog_debug("%s: ri %p dmed", __func__, ri); + zlog_debug("%s: pi %p dmed", __func__, pi); continue; } - bgp_info_unset_flag(rn, ri, BGP_INFO_DMED_CHECK); + bgp_path_info_unset_flag(rn, pi, BGP_PATH_DMED_CHECK); - if (bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi)) { - new_select = ri; + if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg, + debug, pfx_buf, afi, safi)) { + new_select = pi; } } @@ -1987,7 +1993,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, */ if (debug) { if (new_select) - bgp_info_path_with_addpath_rx_str(new_select, path_buf); + bgp_path_info_path_with_addpath_rx_str(new_select, + path_buf); else sprintf(path_buf, "NONE"); zlog_debug( @@ -1997,31 +2004,32 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, } if (do_mpath && new_select) { - for (ri = rn->info; (ri != NULL) && (nextri = ri->next, 1); - ri = nextri) { + for (pi = rn->info; (pi != NULL) && (nextpi = pi->next, 1); + pi = nextpi) { if (debug) - bgp_info_path_with_addpath_rx_str(ri, path_buf); + bgp_path_info_path_with_addpath_rx_str( + pi, path_buf); - if (ri == new_select) { + if (pi == new_select) { if (debug) zlog_debug( "%s: %s is the bestpath, add to the multipath list", pfx_buf, path_buf); - bgp_mp_list_add(&mp_list, ri); + bgp_mp_list_add(&mp_list, pi); continue; } - if (BGP_INFO_HOLDDOWN(ri)) + if (BGP_PATH_HOLDDOWN(pi)) continue; - if (ri->peer && ri->peer != bgp->peer_self - && !CHECK_FLAG(ri->peer->sflags, + if (pi->peer && pi->peer != bgp->peer_self + && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT)) - if (ri->peer->status != Established) + if (pi->peer->status != Established) continue; - if (!bgp_info_nexthop_cmp(ri, new_select)) { + if (!bgp_path_info_nexthop_cmp(pi, new_select)) { if (debug) zlog_debug( "%s: %s has the same nexthop as the bestpath, skip it", @@ -2029,21 +2037,22 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, continue; } - bgp_info_cmp(bgp, ri, new_select, &paths_eq, mpath_cfg, - debug, pfx_buf, afi, safi); + bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, + mpath_cfg, debug, pfx_buf, afi, safi); if (paths_eq) { if (debug) zlog_debug( "%s: %s is equivalent to the bestpath, add to the multipath list", pfx_buf, path_buf); - bgp_mp_list_add(&mp_list, ri); + bgp_mp_list_add(&mp_list, pi); } } } - bgp_info_mpath_update(rn, new_select, old_select, &mp_list, mpath_cfg); - bgp_info_mpath_aggregate_update(new_select, old_select); + bgp_path_info_mpath_update(rn, new_select, old_select, &mp_list, + mpath_cfg); + bgp_path_info_mpath_aggregate_update(new_select, old_select); bgp_mp_list_clear(&mp_list); result->old = old_select; @@ -2057,7 +2066,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, * for advertisement to the subgroup. */ int subgroup_process_announce_selected(struct update_subgroup *subgrp, - struct bgp_info *selected, + struct bgp_path_info *selected, struct bgp_node *rn, uint32_t addpath_tx_id) { @@ -2112,13 +2121,13 @@ int subgroup_process_announce_selected(struct update_subgroup *subgrp, */ void bgp_zebra_clear_route_change_flags(struct bgp_node *rn) { - struct bgp_info *ri; + struct bgp_path_info *pi; - for (ri = rn->info; ri; ri = ri->next) { - if (BGP_INFO_HOLDDOWN(ri)) + for (pi = rn->info; pi; pi = pi->next) { + if (BGP_PATH_HOLDDOWN(pi)) continue; - UNSET_FLAG(ri->flags, BGP_INFO_IGP_CHANGED); - UNSET_FLAG(ri->flags, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG(pi->flags, BGP_PATH_IGP_CHANGED); + UNSET_FLAG(pi->flags, BGP_PATH_ATTR_CHANGED); } } @@ -2127,9 +2136,10 @@ void bgp_zebra_clear_route_change_flags(struct bgp_node *rn) * if the route selection returns the same best route as earlier - to * determine if we need to update zebra or not. */ -int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected) +int bgp_zebra_has_route_changed(struct bgp_node *rn, + struct bgp_path_info *selected) { - struct bgp_info *mpinfo; + struct bgp_path_info *mpinfo; /* If this is multipath, check all selected paths for any nexthop * change or attribute change. Some attribute changes (e.g., community) @@ -2137,17 +2147,17 @@ int bgp_zebra_has_route_changed(struct bgp_node *rn, struct bgp_info *selected) * we handle the case of BGP nexthop change. This is the behavior * when the best path has an attribute change anyway. */ - if (CHECK_FLAG(selected->flags, BGP_INFO_IGP_CHANGED) - || CHECK_FLAG(selected->flags, BGP_INFO_MULTIPATH_CHG)) + if (CHECK_FLAG(selected->flags, BGP_PATH_IGP_CHANGED) + || CHECK_FLAG(selected->flags, BGP_PATH_MULTIPATH_CHG)) return 1; /* * If this is multipath, check all selected paths for any nexthop change */ - for (mpinfo = bgp_info_mpath_first(selected); mpinfo; - mpinfo = bgp_info_mpath_next(mpinfo)) { - if (CHECK_FLAG(mpinfo->flags, BGP_INFO_IGP_CHANGED) - || CHECK_FLAG(mpinfo->flags, BGP_INFO_ATTR_CHANGED)) + for (mpinfo = bgp_path_info_mpath_first(selected); mpinfo; + mpinfo = bgp_path_info_mpath_next(mpinfo)) { + if (CHECK_FLAG(mpinfo->flags, BGP_PATH_IGP_CHANGED) + || CHECK_FLAG(mpinfo->flags, BGP_PATH_ATTR_CHANGED)) return 1; } @@ -2185,9 +2195,9 @@ struct bgp_process_queue { static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, afi_t afi, safi_t safi) { - struct bgp_info *new_select; - struct bgp_info *old_select; - struct bgp_info_pair old_and_new; + struct bgp_path_info *new_select; + struct bgp_path_info *old_select; + struct bgp_path_info_pair old_and_new; char pfx_buf[PREFIX2STR_BUFFER]; int debug = 0; @@ -2269,7 +2279,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, */ if (old_select && old_select == new_select && !CHECK_FLAG(rn->flags, BGP_NODE_USER_CLEAR) - && !CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp->addpath_tx_used[afi][safi]) { if (bgp_zebra_has_route_changed(rn, old_select)) { #if ENABLE_BGP_VNC @@ -2288,12 +2298,12 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, bgp, afi, safi); } } - UNSET_FLAG(old_select->flags, BGP_INFO_MULTIPATH_CHG); + UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(rn); /* If there is a change of interest to peers, reannounce the * route. */ - if (CHECK_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED) + if (CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) || CHECK_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED)) { group_announce_route(bgp, afi, safi, rn, new_select); @@ -2304,7 +2314,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, SAFI_LABELED_UNICAST, rn, new_select); - UNSET_FLAG(old_select->flags, BGP_INFO_ATTR_CHANGED); + UNSET_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED); UNSET_FLAG(rn->flags, BGP_NODE_LABEL_CHANGED); } @@ -2331,13 +2341,13 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, } if (old_select) - bgp_info_unset_flag(rn, old_select, BGP_INFO_SELECTED); + bgp_path_info_unset_flag(rn, old_select, BGP_PATH_SELECTED); if (new_select) { if (debug) zlog_debug("%s: setting SELECTED flag", __func__); - bgp_info_set_flag(rn, new_select, BGP_INFO_SELECTED); - bgp_info_unset_flag(rn, new_select, BGP_INFO_ATTR_CHANGED); - UNSET_FLAG(new_select->flags, BGP_INFO_MULTIPATH_CHG); + bgp_path_info_set_flag(rn, new_select, BGP_PATH_SELECTED); + bgp_path_info_unset_flag(rn, new_select, BGP_PATH_ATTR_CHANGED); + UNSET_FLAG(new_select->flags, BGP_PATH_MULTIPATH_CHG); } #if ENABLE_BGP_VNC @@ -2424,9 +2434,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_node *rn, /* Clear any route change flags. */ bgp_zebra_clear_route_change_flags(rn); - /* Reap old select bgp_info, if it has been removed */ - if (old_select && CHECK_FLAG(old_select->flags, BGP_INFO_REMOVED)) - bgp_info_reap(rn, old_select); + /* Reap old select bgp_path_info, if it has been removed */ + if (old_select && CHECK_FLAG(old_select->flags, BGP_PATH_REMOVED)) + bgp_path_info_reap(rn, old_select); UNSET_FLAG(rn->flags, BGP_NODE_PROCESS_SCHEDULED); return; @@ -2669,29 +2679,29 @@ int bgp_maximum_prefix_overflow(struct peer *peer, afi_t afi, safi_t safi, /* Unconditionally remove the route from the RIB, without taking * damping into consideration (eg, because the session went down) */ -void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, struct peer *peer, - afi_t afi, safi_t safi) +void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi, + struct peer *peer, afi_t afi, safi_t safi) { - bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, safi); + bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi); - if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) - bgp_info_delete(rn, ri); /* keep historical info */ + if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) + bgp_path_info_delete(rn, pi); /* keep historical info */ bgp_process(peer->bgp, rn, afi, safi); } -static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri, +static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_path_info *pi, struct peer *peer, afi_t afi, safi_t safi, struct prefix_rd *prd) { /* apply dampening, if result is suppressed, we'll be retaining - * the bgp_info in the RIB for historical reference. + * the bgp_path_info in the RIB for historical reference. */ if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) - if ((bgp_damp_withdraw(ri, rn, afi, safi, 0)) + if ((bgp_damp_withdraw(pi, rn, afi, safi, 0)) == BGP_DAMP_SUPPRESSED) { - bgp_aggregate_decrement(peer->bgp, &rn->p, ri, afi, + bgp_aggregate_decrement(peer->bgp, &rn->p, pi, afi, safi); return; } @@ -2707,35 +2717,35 @@ static void bgp_rib_withdraw(struct bgp_node *rn, struct bgp_info *ri, table = (struct bgp_table *)(prn->info); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - peer->bgp, prd, table, &rn->p, ri); + peer->bgp, prd, table, &rn->p, pi); } bgp_unlock_node(prn); } if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { - vnc_import_bgp_del_route(peer->bgp, &rn->p, ri); + vnc_import_bgp_del_route(peer->bgp, &rn->p, pi); vnc_import_bgp_exterior_del_route(peer->bgp, &rn->p, - ri); + pi); } } #endif /* If this is an EVPN route, process for un-import. */ if (safi == SAFI_EVPN) - bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, ri); + bgp_evpn_unimport_route(peer->bgp, afi, safi, &rn->p, pi); - bgp_rib_remove(rn, ri, peer, afi, safi); + bgp_rib_remove(rn, pi, peer, afi, safi); } -struct bgp_info *info_make(int type, int sub_type, unsigned short instance, - struct peer *peer, struct attr *attr, - struct bgp_node *rn) +struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance, + struct peer *peer, struct attr *attr, + struct bgp_node *rn) { - struct bgp_info *new; + struct bgp_path_info *new; /* Make new BGP info. */ - new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_info)); + new = XCALLOC(MTYPE_BGP_ROUTE, sizeof(struct bgp_path_info)); new->type = type; new->instance = instance; new->sub_type = sub_type; @@ -2769,12 +2779,12 @@ static void overlay_index_update(struct attr *attr, } } -static bool overlay_index_equal(afi_t afi, struct bgp_info *info, +static bool overlay_index_equal(afi_t afi, struct bgp_path_info *path, struct eth_segment_id *eth_s_id, union gw_addr *gw_ip) { - struct eth_segment_id *info_eth_s_id, *info_eth_s_id_remote; - union gw_addr *info_gw_ip, *info_gw_ip_remote; + struct eth_segment_id *path_eth_s_id, *path_eth_s_id_remote; + union gw_addr *path_gw_ip, *path_gw_ip_remote; union { struct eth_segment_id esi; union gw_addr ip; @@ -2782,34 +2792,34 @@ static bool overlay_index_equal(afi_t afi, struct bgp_info *info, if (afi != AFI_L2VPN) return true; - if (!info->attr) { + if (!path->attr) { memset(&temp, 0, sizeof(temp)); - info_eth_s_id = &temp.esi; - info_gw_ip = &temp.ip; + path_eth_s_id = &temp.esi; + path_gw_ip = &temp.ip; if (eth_s_id == NULL && gw_ip == NULL) return true; } else { - info_eth_s_id = &(info->attr->evpn_overlay.eth_s_id); - info_gw_ip = &(info->attr->evpn_overlay.gw_ip); + path_eth_s_id = &(path->attr->evpn_overlay.eth_s_id); + path_gw_ip = &(path->attr->evpn_overlay.gw_ip); } if (gw_ip == NULL) { memset(&temp, 0, sizeof(temp)); - info_gw_ip_remote = &temp.ip; + path_gw_ip_remote = &temp.ip; } else - info_gw_ip_remote = gw_ip; + path_gw_ip_remote = gw_ip; if (eth_s_id == NULL) { memset(&temp, 0, sizeof(temp)); - info_eth_s_id_remote = &temp.esi; + path_eth_s_id_remote = &temp.esi; } else - info_eth_s_id_remote = eth_s_id; + path_eth_s_id_remote = eth_s_id; - if (!memcmp(info_gw_ip, info_gw_ip_remote, sizeof(union gw_addr))) + if (!memcmp(path_gw_ip, path_gw_ip_remote, sizeof(union gw_addr))) return false; - return !memcmp(info_eth_s_id, info_eth_s_id_remote, + return !memcmp(path_eth_s_id, path_eth_s_id_remote, sizeof(struct eth_segment_id)); } @@ -2878,9 +2888,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, struct bgp *bgp; struct attr new_attr; struct attr *attr_new; - struct bgp_info *ri; - struct bgp_info *new; - struct bgp_info_extra *extra; + struct bgp_path_info *pi; + struct bgp_path_info *new; + struct bgp_path_info_extra *extra; const char *reason; char pfx_buf[BGP_PRD_PATH_STRLEN]; int connected = 0; @@ -2911,10 +2921,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, bgp_adj_in_set(rn, peer, attr, addpath_id); /* Check previously received route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer && ri->type == type - && ri->sub_type == sub_type - && ri->addpath_rx_id == addpath_id) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == peer && pi->type == type + && pi->sub_type == sub_type + && pi->addpath_rx_id == addpath_id) break; /* AS path local-as loop check. */ @@ -3014,24 +3024,24 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, attr_new = bgp_attr_intern(&new_attr); /* If the update is implicit withdraw. */ - if (ri) { - ri->uptime = bgp_clock(); - same_attr = attrhash_cmp(ri->attr, attr_new); + if (pi) { + pi->uptime = bgp_clock(); + same_attr = attrhash_cmp(pi->attr, attr_new); /* Same attribute comes in. */ - if (!CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) - && attrhash_cmp(ri->attr, attr_new) + if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) + && attrhash_cmp(pi->attr, attr_new) && (!has_valid_label - || memcmp(&(bgp_info_extra_get(ri))->label, label, + || memcmp(&(bgp_path_info_extra_get(pi))->label, label, num_labels * sizeof(mpls_label_t)) == 0) && (overlay_index_equal( - afi, ri, evpn == NULL ? NULL : &evpn->eth_s_id, + afi, pi, evpn == NULL ? NULL : &evpn->eth_s_id, evpn == NULL ? NULL : &evpn->gw_ip))) { if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP - && CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) { + && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { if (bgp_debug_update(peer, p, NULL, 1)) { bgp_debug_rdpfxpath2str( afi, safi, prd, p, label, @@ -3042,9 +3052,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, pfx_buf); } - if (bgp_damp_update(ri, rn, afi, safi) + if (bgp_damp_update(pi, rn, afi, safi) != BGP_DAMP_SUPPRESSED) { - bgp_aggregate_increment(bgp, p, ri, afi, + bgp_aggregate_increment(bgp, p, pi, afi, safi); bgp_process(bgp, rn, afi, safi); } @@ -3070,9 +3080,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* graceful restart STALE flag unset. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) { - bgp_info_unset_flag(rn, ri, - BGP_INFO_STALE); + if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) { + bgp_path_info_unset_flag( + rn, pi, BGP_PATH_STALE); bgp_process(bgp, rn, afi, safi); } } @@ -3084,7 +3094,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* Withdraw/Announce before we fully processed the withdraw */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { if (bgp_debug_update(peer, p, NULL, 1)) { bgp_debug_rdpfxpath2str( afi, safi, prd, p, label, num_labels, @@ -3095,7 +3105,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, peer->host, pfx_buf); } - bgp_info_restore(rn, ri); + bgp_path_info_restore(rn, pi); } /* Received Logging. */ @@ -3108,16 +3118,16 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* graceful restart STALE flag unset. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) - bgp_info_unset_flag(rn, ri, BGP_INFO_STALE); + if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) + bgp_path_info_unset_flag(rn, pi, BGP_PATH_STALE); /* The attribute is changed. */ - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED); /* implicit withdraw, decrement aggregate and pcount here. * only if update is accepted, they'll increment below. */ - bgp_aggregate_decrement(bgp, p, ri, afi, safi); + bgp_aggregate_decrement(bgp, p, pi, afi, safi); /* Update bgp route dampening information. */ if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) @@ -3125,8 +3135,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, /* This is implicit withdraw so we should update dampening information. */ - if (!CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) - bgp_damp_withdraw(ri, rn, afi, safi, 1); + if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) + bgp_damp_withdraw(pi, rn, afi, safi, 1); } #if ENABLE_BGP_VNC if (safi == SAFI_MPLS_VPN) { @@ -3139,19 +3149,19 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, table = (struct bgp_table *)(prn->info); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - bgp, prd, table, p, ri); + bgp, prd, table, p, pi); } bgp_unlock_node(prn); } if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { /* * Implicit withdraw case. */ ++vnc_implicit_withdraw; - vnc_import_bgp_del_route(bgp, p, ri); - vnc_import_bgp_exterior_del_route(bgp, p, ri); + vnc_import_bgp_del_route(bgp, p, pi); + vnc_import_bgp_exterior_del_route(bgp, p, pi); } } #endif @@ -3164,35 +3174,35 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * community. */ if (safi == SAFI_EVPN && !same_attr) { - if ((ri->attr->flag + if ((pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) && (attr_new->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) { int cmp; - cmp = ecommunity_cmp(ri->attr->ecommunity, + cmp = ecommunity_cmp(pi->attr->ecommunity, attr_new->ecommunity); if (!cmp) { if (bgp_debug_update(peer, p, NULL, 1)) zlog_debug( "Change in EXT-COMM, existing %s new %s", ecommunity_str( - ri->attr->ecommunity), + pi->attr->ecommunity), ecommunity_str( attr_new->ecommunity)); bgp_evpn_unimport_route(bgp, afi, safi, - p, ri); + p, pi); } } } /* Update to new attribute. */ - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; /* Update MPLS label */ if (has_valid_label) { - extra = bgp_info_extra_get(ri); + extra = bgp_path_info_extra_get(pi); memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t)); extra->num_labels = num_labels; @@ -3217,15 +3227,15 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * changes) which * trigger re-importation of the entire RIB. */ - vnc_import_bgp_add_route(bgp, p, ri); - vnc_import_bgp_exterior_add_route(bgp, p, ri); + vnc_import_bgp_add_route(bgp, p, pi); + vnc_import_bgp_exterior_add_route(bgp, p, pi); } } #endif /* Update Overlay Index */ if (afi == AFI_L2VPN) { overlay_index_update( - ri->attr, evpn == NULL ? NULL : &evpn->eth_s_id, + pi->attr, evpn == NULL ? NULL : &evpn->eth_s_id, evpn == NULL ? NULL : &evpn->gw_ip); } @@ -3233,7 +3243,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING) && peer->sort == BGP_PEER_EBGP) { /* Now we do normal update dampening. */ - ret = bgp_damp_update(ri, rn, afi, safi); + ret = bgp_damp_update(pi, rn, afi, safi); if (ret == BGP_DAMP_SUPPRESSED) { bgp_unlock_node(rn); return 0; @@ -3255,13 +3265,13 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, struct bgp *bgp_nexthop = bgp; - if (ri->extra && ri->extra->bgp_orig) - bgp_nexthop = ri->extra->bgp_orig; + if (pi->extra && pi->extra->bgp_orig) + bgp_nexthop = pi->extra->bgp_orig; - if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, - ri, NULL, connected) + if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi, + NULL, connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) - bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { char buf1[INET6_ADDRSTRLEN]; @@ -3272,10 +3282,11 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); } - bgp_info_unset_flag(rn, ri, BGP_INFO_VALID); + bgp_path_info_unset_flag(rn, pi, + BGP_PATH_VALID); } } else - bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID); #if ENABLE_BGP_VNC if (safi == SAFI_MPLS_VPN) { @@ -3288,7 +3299,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, table = (struct bgp_table *)(prn->info); vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( - bgp, prd, table, p, ri); + bgp, prd, table, p, pi); } bgp_unlock_node(prn); } @@ -3307,10 +3318,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * the attributes for the route in the VNI(s). */ if (safi == SAFI_EVPN && !same_attr) - bgp_evpn_import_route(bgp, afi, safi, p, ri); + bgp_evpn_import_route(bgp, afi, safi, p, pi); /* Process change. */ - bgp_aggregate_increment(bgp, p, ri, afi, safi); + bgp_aggregate_increment(bgp, p, pi, afi, safi); bgp_process(bgp, rn, afi, safi); bgp_unlock_node(rn); @@ -3319,12 +3330,12 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_from_vrf_update(bgp_get_default(), bgp, ri); + vpn_leak_from_vrf_update(bgp_get_default(), bgp, pi); } if ((SAFI_MPLS_VPN == safi) && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_to_vrf_update(bgp, ri); + vpn_leak_to_vrf_update(bgp, pi); } #if ENABLE_BGP_VNC @@ -3362,7 +3373,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, /* Update MPLS label */ if (has_valid_label) { - extra = bgp_info_extra_get(new); + extra = bgp_path_info_extra_get(new); memcpy(&extra->label, label, num_labels * sizeof(mpls_label_t)); extra->num_labels = num_labels; if (!(afi == AFI_L2VPN && safi == SAFI_EVPN)) @@ -3388,7 +3399,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) - bgp_info_set_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { char buf1[INET6_ADDRSTRLEN]; @@ -3398,10 +3409,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, zlog_debug("%s(%s): NH unresolved", __FUNCTION__, buf1); } - bgp_info_unset_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID); } } else - bgp_info_set_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); /* Addpath ID */ new->addpath_rx_id = addpath_id; @@ -3410,7 +3421,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, bgp_aggregate_increment(bgp, p, new, afi, safi); /* Register new BGP information. */ - bgp_info_add(rn, new); + bgp_path_info_add(rn, new); /* route_node_get lock */ bgp_unlock_node(rn); @@ -3485,25 +3496,25 @@ filtered: peer->host, pfx_buf, reason); } - if (ri) { + if (pi) { /* If this is an EVPN route, un-import it as it is now filtered. */ if (safi == SAFI_EVPN) - bgp_evpn_unimport_route(bgp, afi, safi, p, ri); + bgp_evpn_unimport_route(bgp, afi, safi, p, pi); if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri); + vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi); } if ((SAFI_MPLS_VPN == safi) && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_to_vrf_withdraw(bgp, ri); + vpn_leak_to_vrf_withdraw(bgp, pi); } - bgp_rib_remove(rn, ri, peer, afi, safi); + bgp_rib_remove(rn, pi, peer, afi, safi); } bgp_unlock_node(rn); @@ -3531,7 +3542,7 @@ int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id, struct bgp *bgp; char pfx_buf[BGP_PRD_PATH_STRLEN]; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; #if ENABLE_BGP_VNC if ((SAFI_MPLS_VPN == safi) || (SAFI_ENCAP == safi)) { @@ -3573,10 +3584,10 @@ int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* Lookup withdrawn route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == peer && ri->type == type - && ri->sub_type == sub_type - && ri->addpath_rx_id == addpath_id) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == peer && pi->type == type + && pi->sub_type == sub_type + && pi->addpath_rx_id == addpath_id) break; /* Logging. */ @@ -3589,17 +3600,17 @@ int bgp_withdraw(struct peer *peer, struct prefix *p, uint32_t addpath_id, } /* Withdraw specified route from routing table. */ - if (ri && !CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) { - bgp_rib_withdraw(rn, ri, peer, afi, safi, prd); + if (pi && !CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) { + bgp_rib_withdraw(rn, pi, peer, afi, safi, prd); if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri); + vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi); } if ((SAFI_MPLS_VPN == safi) && (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_to_vrf_withdraw(bgp, ri); + vpn_leak_to_vrf_withdraw(bgp, pi); } } else if (bgp_debug_update(peer, p, NULL, 1)) { bgp_debug_rdpfxpath2str(afi, safi, prd, p, label, num_labels, @@ -3727,14 +3738,14 @@ static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, if (ain->peer != peer) continue; - struct bgp_info *ri = rn->info; + struct bgp_path_info *pi = rn->info; uint32_t num_labels = 0; mpls_label_t *label_pnt = NULL; - if (ri && ri->extra) - num_labels = ri->extra->num_labels; + if (pi && pi->extra) + num_labels = pi->extra->num_labels; if (num_labels) - label_pnt = &ri->extra->label[0]; + label_pnt = &pi->extra->label[0]; ret = bgp_update(peer, &rn->p, ain->addpath_rx_id, ain->attr, afi, safi, ZEBRA_ROUTE_BGP, @@ -3783,7 +3794,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) struct bgp_clear_node_queue *cnq = data; struct bgp_node *rn = cnq->rn; struct peer *peer = wq->spec.data; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp *bgp; afi_t afi = bgp_node_table(rn)->afi; safi_t safi = bgp_node_table(rn)->safi; @@ -3794,35 +3805,35 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data) /* It is possible that we have multiple paths for a prefix from a peer * if that peer is using AddPath. */ - for (ri = rn->info; ri; ri = ri->next) { - if (ri->peer != peer) + for (pi = rn->info; pi; pi = pi->next) { + if (pi->peer != peer) continue; /* graceful restart STALE flag set. */ if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT) && peer->nsf[afi][safi] - && !CHECK_FLAG(ri->flags, BGP_INFO_STALE) - && !CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) - bgp_info_set_flag(rn, ri, BGP_INFO_STALE); + && !CHECK_FLAG(pi->flags, BGP_PATH_STALE) + && !CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) + bgp_path_info_set_flag(rn, pi, BGP_PATH_STALE); else { /* If this is an EVPN route, process for * un-import. */ if (safi == SAFI_EVPN) - bgp_evpn_unimport_route(bgp, afi, safi, - &rn->p, ri); + bgp_evpn_unimport_route(bgp, afi, safi, &rn->p, + pi); /* Handle withdraw for VRF route-leaking and L3VPN */ if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_withdraw(bgp_get_default(), - bgp, ri); + bgp, pi); } if (SAFI_MPLS_VPN == safi && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { - vpn_leak_to_vrf_withdraw(bgp, ri); + vpn_leak_to_vrf_withdraw(bgp, pi); } - bgp_rib_remove(rn, ri, peer, afi, safi); + bgp_rib_remove(rn, pi, peer, afi, safi); } } return WQ_SUCCESS; @@ -3882,7 +3893,7 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, return; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - struct bgp_info *ri, *next; + struct bgp_path_info *pi, *next; struct bgp_adj_in *ain; struct bgp_adj_in *ain_next; @@ -3933,13 +3944,13 @@ static void bgp_clear_route_table(struct peer *peer, afi_t afi, safi_t safi, ain = ain_next; } - for (ri = rn->info; ri; ri = next) { - next = ri->next; - if (ri->peer != peer) + for (pi = rn->info; pi; pi = next) { + next = pi->next; + if (pi->peer != peer) continue; if (force) - bgp_info_reap(rn, ri); + bgp_path_info_reap(rn, pi); else { struct bgp_clear_node_queue *cnq; @@ -4043,7 +4054,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi) void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_table *table; if (safi == SAFI_MPLS_VPN) { @@ -4057,26 +4068,26 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi) for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) - for (ri = rm->info; ri; ri = ri->next) { - if (ri->peer != peer) + for (pi = rm->info; pi; pi = pi->next) { + if (pi->peer != peer) continue; - if (!CHECK_FLAG(ri->flags, - BGP_INFO_STALE)) + if (!CHECK_FLAG(pi->flags, + BGP_PATH_STALE)) break; - bgp_rib_remove(rm, ri, peer, afi, safi); + bgp_rib_remove(rm, pi, peer, afi, safi); break; } } } else { for (rn = bgp_table_top(peer->bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = ri->next) { - if (ri->peer != peer) + for (pi = rn->info; pi; pi = pi->next) { + if (pi->peer != peer) continue; - if (!CHECK_FLAG(ri->flags, BGP_INFO_STALE)) + if (!CHECK_FLAG(pi->flags, BGP_PATH_STALE)) break; - bgp_rib_remove(rn, ri, peer, afi, safi); + bgp_rib_remove(rn, pi, peer, afi, safi); break; } } @@ -4086,22 +4097,22 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, safi_t safi) { struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_info *next; + struct bgp_path_info *pi; + struct bgp_path_info *next; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = next) { - next = ri->next; - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) - && ri->type == ZEBRA_ROUTE_BGP - && (ri->sub_type == BGP_ROUTE_NORMAL - || ri->sub_type == BGP_ROUTE_AGGREGATE - || ri->sub_type == BGP_ROUTE_IMPORTED)) { + for (pi = rn->info; pi; pi = next) { + next = pi->next; + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) + && pi->type == ZEBRA_ROUTE_BGP + && (pi->sub_type == BGP_ROUTE_NORMAL + || pi->sub_type == BGP_ROUTE_AGGREGATE + || pi->sub_type == BGP_ROUTE_IMPORTED)) { if (bgp_fibupd_safi(safi)) - bgp_zebra_withdraw(&rn->p, ri, - bgp, safi); - bgp_info_reap(rn, ri); + bgp_zebra_withdraw(&rn->p, pi, bgp, + safi); + bgp_path_info_reap(rn, pi); } } } @@ -4352,9 +4363,9 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, struct bgp_static *bgp_static, afi_t afi, safi_t safi) { struct bgp_node *rn; - struct bgp_info *ri; - struct bgp_info *new; - struct bgp_info info; + struct bgp_path_info *pi; + struct bgp_path_info *new; + struct bgp_path_info rmap_path; struct attr attr; struct attr *attr_new; int ret; @@ -4387,13 +4398,14 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, if (bgp_static->rmap.name) { struct attr attr_tmp = attr; - memset(&info, 0, sizeof(struct bgp_info)); - info.peer = bgp->peer_self; - info.attr = &attr_tmp; + memset(&rmap_path, 0, sizeof(struct bgp_path_info)); + rmap_path.peer = bgp->peer_self; + rmap_path.attr = &attr_tmp; SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); + ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, + &rmap_path); bgp->peer_self->rmap_type = 0; @@ -4419,14 +4431,14 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, attr_new = bgp_attr_intern(&attr); } - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) break; - if (ri) { - if (attrhash_cmp(ri->attr, attr_new) - && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED) + if (pi) { + if (attrhash_cmp(pi->attr, attr_new) + && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && !bgp_flag_check(bgp, BGP_FLAG_FORCE_STATIC_PROCESS)) { bgp_unlock_node(rn); bgp_attr_unintern(&attr_new); @@ -4434,39 +4446,39 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, return; } else { /* The attribute is changed. */ - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED); /* Rewrite BGP route information. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, pi); else - bgp_aggregate_decrement(bgp, p, ri, afi, safi); + bgp_aggregate_decrement(bgp, p, pi, afi, safi); #if ENABLE_BGP_VNC if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { /* * Implicit withdraw case. - * We have to do this before ri is + * We have to do this before pi is * changed */ ++vnc_implicit_withdraw; - vnc_import_bgp_del_route(bgp, p, ri); + vnc_import_bgp_del_route(bgp, p, pi); vnc_import_bgp_exterior_del_route( - bgp, p, ri); + bgp, p, pi); } } #endif - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock(); + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; + pi->uptime = bgp_clock(); #if ENABLE_BGP_VNC if ((afi == AFI_IP || afi == AFI_IP6) && (safi == SAFI_UNICAST)) { if (vnc_implicit_withdraw) { - vnc_import_bgp_add_route(bgp, p, ri); + vnc_import_bgp_add_route(bgp, p, pi); vnc_import_bgp_exterior_add_route( - bgp, p, ri); + bgp, p, pi); } } #endif @@ -4478,13 +4490,13 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, struct bgp *bgp_nexthop = bgp; - if (ri->extra && ri->extra->bgp_orig) - bgp_nexthop = ri->extra->bgp_orig; + if (pi->extra && pi->extra->bgp_orig) + bgp_nexthop = pi->extra->bgp_orig; if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, - afi, ri, NULL, 0)) - bgp_info_set_flag(rn, ri, - BGP_INFO_VALID); + afi, pi, NULL, 0)) + bgp_path_info_set_flag(rn, pi, + BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { char buf1[INET6_ADDRSTRLEN]; @@ -4495,8 +4507,8 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, "%s(%s): Route not in table, not advertising", __FUNCTION__, buf1); } - bgp_info_unset_flag(rn, ri, - BGP_INFO_VALID); + bgp_path_info_unset_flag( + rn, pi, BGP_PATH_VALID); } } else { /* Delete the NHT structure if any, if we're @@ -4506,11 +4518,11 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, * from NHT to avoid overloading NHT and the * process interaction */ - bgp_unlink_nexthop(ri); - bgp_info_set_flag(rn, ri, BGP_INFO_VALID); + bgp_unlink_nexthop(pi); + bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID); } /* Process change. */ - bgp_aggregate_increment(bgp, p, ri, afi, safi); + bgp_aggregate_increment(bgp, p, pi, afi, safi); bgp_process(bgp, rn, afi, safi); if (SAFI_UNICAST == safi @@ -4518,7 +4530,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_update(bgp_get_default(), bgp, - ri); + pi); } bgp_unlock_node(rn); @@ -4534,7 +4546,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, if (bgp_flag_check(bgp, BGP_FLAG_IMPORT_CHECK) && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, 0)) - bgp_info_set_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { char buf1[INET6_ADDRSTRLEN]; @@ -4544,7 +4556,7 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, "%s(%s): Route not in table, not advertising", __FUNCTION__, buf1); } - bgp_info_unset_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_unset_flag(rn, new, BGP_PATH_VALID); } } else { /* Delete the NHT structure if any, if we're toggling between @@ -4553,14 +4565,14 @@ void bgp_static_update(struct bgp *bgp, struct prefix *p, */ bgp_unlink_nexthop(new); - bgp_info_set_flag(rn, new, BGP_INFO_VALID); + bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); } /* Aggregate address increment. */ bgp_aggregate_increment(bgp, p, new, afi, safi); /* Register new BGP information. */ - bgp_info_add(rn, new); + bgp_path_info_add(rn, new); /* route_node_get lock */ bgp_unlock_node(rn); @@ -4582,26 +4594,26 @@ void bgp_static_withdraw(struct bgp *bgp, struct prefix *p, afi_t afi, safi_t safi) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, NULL); /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) break; /* Withdraw static BGP route from routing table. */ - if (ri) { + if (pi) { if (SAFI_UNICAST == safi && (bgp->inst_type == BGP_INSTANCE_TYPE_VRF || bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { - vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, ri); + vpn_leak_from_vrf_withdraw(bgp_get_default(), bgp, pi); } - bgp_aggregate_decrement(bgp, p, ri, afi, safi); - bgp_unlink_nexthop(ri); - bgp_info_delete(rn, ri); + bgp_aggregate_decrement(bgp, p, pi, afi, safi); + bgp_unlink_nexthop(pi); + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, safi); } @@ -4617,29 +4629,29 @@ static void bgp_static_withdraw_safi(struct bgp *bgp, struct prefix *p, struct prefix_rd *prd) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; rn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd); /* Check selected route and self inserted route. */ - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) break; /* Withdraw static BGP route from routing table. */ - if (ri) { + if (pi) { #if ENABLE_BGP_VNC rfapiProcessWithdraw( - ri->peer, NULL, p, prd, ri->attr, afi, safi, ri->type, + pi->peer, NULL, p, prd, pi->attr, afi, safi, pi->type, 1); /* Kill, since it is an administrative change */ #endif if (SAFI_MPLS_VPN == safi && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { - vpn_leak_to_vrf_withdraw(bgp, ri); + vpn_leak_to_vrf_withdraw(bgp, pi); } - bgp_aggregate_decrement(bgp, p, ri, afi, safi); - bgp_info_delete(rn, ri); + bgp_aggregate_decrement(bgp, p, pi, afi, safi); + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, safi); } @@ -4652,10 +4664,10 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, safi_t safi) { struct bgp_node *rn; - struct bgp_info *new; + struct bgp_path_info *new; struct attr *attr_new; struct attr attr = {0}; - struct bgp_info *ri; + struct bgp_path_info *pi; #if ENABLE_BGP_VNC mpls_label_t label = 0; #endif @@ -4703,15 +4715,16 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, /* Apply route-map. */ if (bgp_static->rmap.name) { struct attr attr_tmp = attr; - struct bgp_info info; + struct bgp_path_info rmap_path; int ret; - info.peer = bgp->peer_self; - info.attr = &attr_tmp; + rmap_path.peer = bgp->peer_self; + rmap_path.attr = &attr_tmp; SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_NETWORK); - ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, &info); + ret = route_map_apply(bgp_static->rmap.map, p, RMAP_BGP, + &rmap_path); bgp->peer_self->rmap_type = 0; @@ -4731,49 +4744,49 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, attr_new = bgp_attr_intern(&attr); } - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) break; - if (ri) { + if (pi) { memset(&add, 0, sizeof(union gw_addr)); - if (attrhash_cmp(ri->attr, attr_new) - && overlay_index_equal(afi, ri, bgp_static->eth_s_id, &add) - && !CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(pi->attr, attr_new) + && overlay_index_equal(afi, pi, bgp_static->eth_s_id, &add) + && !CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) { bgp_unlock_node(rn); bgp_attr_unintern(&attr_new); aspath_unintern(&attr.aspath); return; } else { /* The attribute is changed. */ - bgp_info_set_flag(rn, ri, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, pi, BGP_PATH_ATTR_CHANGED); /* Rewrite BGP route information. */ - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) - bgp_info_restore(rn, ri); + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(rn, pi); else - bgp_aggregate_decrement(bgp, p, ri, afi, safi); - bgp_attr_unintern(&ri->attr); - ri->attr = attr_new; - ri->uptime = bgp_clock(); + bgp_aggregate_decrement(bgp, p, pi, afi, safi); + bgp_attr_unintern(&pi->attr); + pi->attr = attr_new; + pi->uptime = bgp_clock(); #if ENABLE_BGP_VNC - if (ri->extra) - label = decode_label(&ri->extra->label[0]); + if (pi->extra) + label = decode_label(&pi->extra->label[0]); #endif /* Process change. */ - bgp_aggregate_increment(bgp, p, ri, afi, safi); + bgp_aggregate_increment(bgp, p, pi, afi, safi); bgp_process(bgp, rn, afi, safi); if (SAFI_MPLS_VPN == safi && bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) { - vpn_leak_to_vrf_update(bgp, ri); + vpn_leak_to_vrf_update(bgp, pi); } #if ENABLE_BGP_VNC - rfapiProcessUpdate(ri->peer, NULL, p, &bgp_static->prd, - ri->attr, afi, safi, ri->type, - ri->sub_type, &label); + rfapiProcessUpdate(pi->peer, NULL, p, &bgp_static->prd, + pi->attr, afi, safi, pi->type, + pi->sub_type, &label); #endif bgp_unlock_node(rn); aspath_unintern(&attr.aspath); @@ -4785,8 +4798,8 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, /* Make new BGP info. */ new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_STATIC, 0, bgp->peer_self, attr_new, rn); - SET_FLAG(new->flags, BGP_INFO_VALID); - new->extra = bgp_info_extra_new(); + SET_FLAG(new->flags, BGP_PATH_VALID); + new->extra = bgp_path_info_extra_new(); if (num_labels) { new->extra->label[0] = bgp_static->label; new->extra->num_labels = num_labels; @@ -4799,7 +4812,7 @@ static void bgp_static_update_safi(struct bgp *bgp, struct prefix *p, bgp_aggregate_increment(bgp, p, new, afi, safi); /* Register new BGP information. */ - bgp_info_add(rn, new); + bgp_path_info_add(rn, new); /* route_node_get lock */ bgp_unlock_node(rn); @@ -5071,21 +5084,21 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi, { struct bgp_table *table; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; table = bgp->rib[afi][safi]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) { - if (ri->peer == bgp->peer_self - && ((ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_STATIC) - || (ri->type != ZEBRA_ROUTE_BGP - && ri->sub_type + for (pi = rn->info; pi; pi = pi->next) { + if (pi->peer == bgp->peer_self + && ((pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_STATIC) + || (pi->type != ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_REDISTRIBUTE))) { - bgp_aggregate_decrement(bgp, &rn->p, ri, afi, + bgp_aggregate_decrement(bgp, &rn->p, pi, afi, safi); - bgp_unlink_nexthop(ri); - bgp_info_delete(rn, ri); + bgp_unlink_nexthop(pi); + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, safi); } } @@ -5467,28 +5480,36 @@ static void bgp_aggregate_free(struct bgp_aggregate *aggregate) XFREE(MTYPE_BGP_AGGREGATE, aggregate); } -static int bgp_aggregate_info_same(struct bgp_info *ri, uint8_t origin, +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; if (!ae) ae = aspath_empty(); - if (!ri) + if (!pi) return 0; - if (origin != ri->attr->origin) + if (origin != pi->attr->origin) return 0; - if (!aspath_cmp(ri->attr->aspath, (aspath) ? aspath : ae)) + if (!aspath_cmp(pi->attr->aspath, (aspath) ? aspath : ae)) return 0; - if (!community_cmp(ri->attr->community, comm)) + if (!community_cmp(pi->attr->community, comm)) return 0; - if (!CHECK_FLAG(ri->flags, BGP_INFO_VALID)) + 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; return 1; @@ -5498,20 +5519,22 @@ 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) { struct bgp_node *rn; struct bgp_table *table; - struct bgp_info *ri, *new; + struct bgp_path_info *pi, *new; table = bgp->rib[afi][safi]; rn = bgp_node_get(table, p); - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_AGGREGATE) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_AGGREGATE) break; if (aggregate->count > 0) { @@ -5519,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); + community_free(&community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); return; } @@ -5534,29 +5561,31 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, /* * Mark the old as unusable */ - if (ri) - bgp_info_delete(rn, ri); + 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); - SET_FLAG(new->flags, BGP_INFO_VALID); + 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_info_add(rn, new); + bgp_path_info_add(rn, new); bgp_process(bgp, rn, afi, safi); } else { - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self - && ri->type == ZEBRA_ROUTE_BGP - && ri->sub_type == BGP_ROUTE_AGGREGATE) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self + && pi->type == ZEBRA_ROUTE_BGP + && pi->sub_type == BGP_ROUTE_AGGREGATE) break; /* Withdraw static BGP route from routing table. */ - if (ri) { - bgp_info_delete(rn, ri); + if (pi) { + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, safi); } } @@ -5566,8 +5595,8 @@ static void bgp_aggregate_install(struct bgp *bgp, afi_t afi, safi_t safi, /* Update an aggregate as routes are added/removed from the BGP table */ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, - struct bgp_info *rinew, afi_t afi, safi_t safi, - struct bgp_info *del, + struct bgp_path_info *pinew, afi_t afi, + safi_t safi, struct bgp_path_info *del, struct bgp_aggregate *aggregate) { struct bgp_table *table; @@ -5578,7 +5607,11 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, struct aspath *asmerge = NULL; struct community *community = NULL; struct community *commerge = NULL; - struct bgp_info *ri; + 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; @@ -5602,18 +5635,18 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, match = 0; - for (ri = rn->info; ri; ri = ri->next) { - if (BGP_INFO_HOLDDOWN(ri)) + for (pi = rn->info; pi; pi = pi->next) { + if (BGP_PATH_HOLDDOWN(pi)) continue; - if (del && ri == del) + if (del && pi == del) continue; - if (ri->attr->flag + if (pi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE)) atomic_aggregate = 1; - if (ri->sub_type == BGP_ROUTE_AGGREGATE) + if (pi->sub_type == BGP_ROUTE_AGGREGATE) continue; /* @@ -5621,9 +5654,9 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, * aggregated route announcements. */ if (aggregate->summary_only) { - (bgp_info_extra_get(ri))->suppress++; - bgp_info_set_flag(rn, ri, - BGP_INFO_ATTR_CHANGED); + (bgp_path_info_extra_get(pi))->suppress++; + bgp_path_info_set_flag(rn, pi, + BGP_PATH_ATTR_CHANGED); match++; } @@ -5639,8 +5672,8 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, * route MUST have the ORIGIN attribute with the value * EGP. */ - if (origin < ri->attr->origin) - origin = ri->attr->origin; + if (origin < pi->attr->origin) + origin = pi->attr->origin; if (!aggregate->as_set) continue; @@ -5651,69 +5684,127 @@ static void bgp_aggregate_route(struct bgp *bgp, struct prefix *p, */ if (aspath) { asmerge = aspath_aggregate(aspath, - ri->attr->aspath); + pi->attr->aspath); aspath_free(aspath); aspath = asmerge; } else - aspath = aspath_dup(ri->attr->aspath); + aspath = aspath_dup(pi->attr->aspath); - if (!ri->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, - ri->attr->community); - community = community_uniq_sort(commerge); - community_free(commerge); - } else - community = community_dup(ri->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); } bgp_unlock_node(top); - if (rinew) { + if (pinew) { aggregate->count++; if (aggregate->summary_only) - (bgp_info_extra_get(rinew))->suppress++; + (bgp_path_info_extra_get(pinew))->suppress++; - if (origin < rinew->attr->origin) - origin = rinew->attr->origin; + if (origin < pinew->attr->origin) + origin = pinew->attr->origin; if (aggregate->as_set) { if (aspath) { asmerge = aspath_aggregate(aspath, - rinew->attr->aspath); + pinew->attr->aspath); aspath_free(aspath); aspath = asmerge; } else - aspath = aspath_dup(rinew->attr->aspath); + aspath = aspath_dup(pinew->attr->aspath); - if (rinew->attr->community) { + if (pinew->attr->community) { if (community) { commerge = community_merge( community, - rinew->attr->community); + pinew->attr->community); community = community_uniq_sort(commerge); - community_free(commerge); + community_free(&commerge); } else community = community_dup( - rinew->attr->community); + 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); + community_free(&community); + if (ecommunity) + ecommunity_free(&ecommunity); + if (lcommunity) + lcommunity_free(&lcommunity); } } @@ -5723,7 +5814,7 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, struct bgp_table *table; struct bgp_node *top; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; unsigned long match; table = bgp->rib[afi][safi]; @@ -5736,19 +5827,19 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, continue; match = 0; - for (ri = rn->info; ri; ri = ri->next) { - if (BGP_INFO_HOLDDOWN(ri)) + for (pi = rn->info; pi; pi = pi->next) { + if (BGP_PATH_HOLDDOWN(pi)) continue; - if (ri->sub_type == BGP_ROUTE_AGGREGATE) + if (pi->sub_type == BGP_ROUTE_AGGREGATE) continue; - if (aggregate->summary_only && ri->extra) { - ri->extra->suppress--; + if (aggregate->summary_only && pi->extra) { + pi->extra->suppress--; - if (ri->extra->suppress == 0) { - bgp_info_set_flag( - rn, ri, BGP_INFO_ATTR_CHANGED); + if (pi->extra->suppress == 0) { + bgp_path_info_set_flag( + rn, pi, BGP_PATH_ATTR_CHANGED); match++; } } @@ -5763,7 +5854,7 @@ static void bgp_aggregate_delete(struct bgp *bgp, struct prefix *p, afi_t afi, } void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, - struct bgp_info *ri, afi_t afi, safi_t safi) + struct bgp_path_info *pi, afi_t afi, safi_t safi) { struct bgp_node *child; struct bgp_node *rn; @@ -5779,7 +5870,7 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, if (p->prefixlen == 0) return; - if (BGP_INFO_HOLDDOWN(ri)) + if (BGP_PATH_HOLDDOWN(pi)) return; child = bgp_node_get(table, p); @@ -5789,7 +5880,7 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, aggregate = bgp_aggregate_get_node_info(rn); if (aggregate != NULL && rn->p.prefixlen < p->prefixlen) { bgp_aggregate_delete(bgp, &rn->p, afi, safi, aggregate); - bgp_aggregate_route(bgp, &rn->p, ri, afi, safi, NULL, + bgp_aggregate_route(bgp, &rn->p, pi, afi, safi, NULL, aggregate); } } @@ -5797,7 +5888,7 @@ void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, } void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, - struct bgp_info *del, afi_t afi, safi_t safi) + struct bgp_path_info *del, afi_t afi, safi_t safi) { struct bgp_node *child; struct bgp_node *rn; @@ -5858,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); @@ -6061,9 +6153,9 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, uint8_t type, unsigned short instance, route_tag_t tag) { - struct bgp_info *new; - struct bgp_info *bi; - struct bgp_info info; + struct bgp_path_info *new; + struct bgp_path_info *bpi; + struct bgp_path_info rmap_path; struct bgp_node *bn; struct attr attr; struct attr *new_attr; @@ -6119,15 +6211,15 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, /* Apply route-map. */ if (red->rmap.name) { - memset(&info, 0, sizeof(struct bgp_info)); - info.peer = bgp->peer_self; - info.attr = &attr_new; + memset(&rmap_path, 0, sizeof(struct bgp_path_info)); + rmap_path.peer = bgp->peer_self; + rmap_path.attr = &attr_new; SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_REDISTRIBUTE); ret = route_map_apply(red->rmap.map, p, RMAP_BGP, - &info); + &rmap_path); bgp->peer_self->rmap_type = 0; @@ -6150,37 +6242,37 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, new_attr = bgp_attr_intern(&attr_new); - for (bi = bn->info; bi; bi = bi->next) - if (bi->peer == bgp->peer_self - && bi->sub_type == BGP_ROUTE_REDISTRIBUTE) + for (bpi = bn->info; bpi; bpi = bpi->next) + if (bpi->peer == bgp->peer_self + && bpi->sub_type == BGP_ROUTE_REDISTRIBUTE) break; - if (bi) { + if (bpi) { /* Ensure the (source route) type is updated. */ - bi->type = type; - if (attrhash_cmp(bi->attr, new_attr) - && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + bpi->type = type; + if (attrhash_cmp(bpi->attr, new_attr) + && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { bgp_attr_unintern(&new_attr); aspath_unintern(&attr.aspath); bgp_unlock_node(bn); return; } else { /* The attribute is changed. */ - bgp_info_set_flag(bn, bi, - BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(bn, bpi, + BGP_PATH_ATTR_CHANGED); /* Rewrite BGP route information. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) - bgp_info_restore(bn, bi); + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(bn, bpi); else - bgp_aggregate_decrement(bgp, p, bi, afi, - SAFI_UNICAST); - bgp_attr_unintern(&bi->attr); - bi->attr = new_attr; - bi->uptime = bgp_clock(); + bgp_aggregate_decrement( + bgp, p, bpi, afi, SAFI_UNICAST); + bgp_attr_unintern(&bpi->attr); + bpi->attr = new_attr; + bpi->uptime = bgp_clock(); /* Process change. */ - bgp_aggregate_increment(bgp, p, bi, afi, + bgp_aggregate_increment(bgp, p, bpi, afi, SAFI_UNICAST); bgp_process(bgp, bn, afi, SAFI_UNICAST); bgp_unlock_node(bn); @@ -6191,7 +6283,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_update( - bgp_get_default(), bgp, bi); + bgp_get_default(), bgp, bpi); } return; } @@ -6199,10 +6291,10 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p, new = info_make(type, BGP_ROUTE_REDISTRIBUTE, instance, bgp->peer_self, new_attr, bn); - SET_FLAG(new->flags, BGP_INFO_VALID); + SET_FLAG(new->flags, BGP_PATH_VALID); bgp_aggregate_increment(bgp, p, new, afi, SAFI_UNICAST); - bgp_info_add(bn, new); + bgp_path_info_add(bn, new); bgp_unlock_node(bn); bgp_process(bgp, bn, afi, SAFI_UNICAST); @@ -6222,7 +6314,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type, { afi_t afi; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_redist *red; afi = family2afi(p->family); @@ -6232,19 +6324,19 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type, rn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, p, NULL); - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == type) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == type) break; - if (ri) { + if (pi) { if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF) || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_withdraw(bgp_get_default(), - bgp, ri); + bgp, pi); } - bgp_aggregate_decrement(bgp, p, ri, afi, SAFI_UNICAST); - bgp_info_delete(rn, ri); + bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST); + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, SAFI_UNICAST); } bgp_unlock_node(rn); @@ -6256,27 +6348,27 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type, unsigned short instance) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_table *table; table = bgp->rib[afi][SAFI_UNICAST]; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) - if (ri->peer == bgp->peer_self && ri->type == type - && ri->instance == instance) + for (pi = rn->info; pi; pi = pi->next) + if (pi->peer == bgp->peer_self && pi->type == type + && pi->instance == instance) break; - if (ri) { + if (pi) { if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF) || (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) { vpn_leak_from_vrf_withdraw(bgp_get_default(), - bgp, ri); + bgp, pi); } - bgp_aggregate_decrement(bgp, &rn->p, ri, afi, + bgp_aggregate_decrement(bgp, &rn->p, pi, afi, SAFI_UNICAST); - bgp_info_delete(rn, ri); + bgp_path_info_delete(rn, pi); bgp_process(bgp, rn, afi, SAFI_UNICAST); } } @@ -6302,9 +6394,7 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty, &p->u.prefix, buf, BUFSIZ)); json_object_int_add(json, "prefixLen", p->prefixlen); - sprintf(buf2, "%s/%d", - inet_ntop(p->family, &p->u.prefix, buf, - BUFSIZ), p->prefixlen); + prefix2str(p, buf2, PREFIX_STRLEN); json_object_string_add(json, "network", buf2); } } else if (p->family == AF_ETHERNET) { @@ -6335,10 +6425,9 @@ static void route_vty_out_route(struct prefix *p, struct vty *vty, &p->u.prefix, buf, BUFSIZ)); json_object_int_add(json, "prefixLen", p->prefixlen); - sprintf(buf2, "%s/%d", - inet_ntop(p->family, &p->u.prefix, buf, - BUFSIZ), p->prefixlen); - json_object_string_add(json, "network", buf2); } + prefix2str(p, buf2, PREFIX_STRLEN); + json_object_string_add(json, "network", buf2); + } } if (!json) { @@ -6354,42 +6443,43 @@ enum bgp_display_type { normal_list, }; -/* Print the short form route status for a bgp_info */ -static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo, +/* Print the short form route status for a bgp_path_info */ +static void route_vty_short_status_out(struct vty *vty, + struct bgp_path_info *path, json_object *json_path) { if (json_path) { /* Route status display. */ - if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) json_object_boolean_true_add(json_path, "removed"); - if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) + if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) json_object_boolean_true_add(json_path, "stale"); - if (binfo->extra && binfo->extra->suppress) + if (path->extra && path->extra->suppress) json_object_boolean_true_add(json_path, "suppressed"); - if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) - && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(path->flags, BGP_PATH_VALID) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) json_object_boolean_true_add(json_path, "valid"); /* Selected */ - if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) json_object_boolean_true_add(json_path, "history"); - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) json_object_boolean_true_add(json_path, "damped"); - if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) json_object_boolean_true_add(json_path, "bestpath"); - if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) + if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)) json_object_boolean_true_add(json_path, "multipath"); /* Internal route. */ - if ((binfo->peer->as) - && (binfo->peer->as == binfo->peer->local_as)) + if ((path->peer->as) + && (path->peer->as == path->peer->local_as)) json_object_string_add(json_path, "pathFrom", "internal"); else @@ -6400,41 +6490,42 @@ static void route_vty_short_status_out(struct vty *vty, struct bgp_info *binfo, } /* Route status display. */ - if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) vty_out(vty, "R"); - else if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) + else if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) vty_out(vty, "S"); - else if (binfo->extra && binfo->extra->suppress) + else if (path->extra && path->extra->suppress) vty_out(vty, "s"); - else if (CHECK_FLAG(binfo->flags, BGP_INFO_VALID) - && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + else if (CHECK_FLAG(path->flags, BGP_PATH_VALID) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, "*"); else vty_out(vty, " "); /* Selected */ - if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) vty_out(vty, "h"); - else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) + else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) vty_out(vty, "d"); - else if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) vty_out(vty, ">"); - else if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH)) + else if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH)) vty_out(vty, "="); else vty_out(vty, " "); /* Internal route. */ - if (binfo->peer && (binfo->peer->as) - && (binfo->peer->as == binfo->peer->local_as)) + if (path->peer && (path->peer->as) + && (path->peer->as == path->peer->local_as)) vty_out(vty, "i"); else vty_out(vty, " "); } /* called from terminal list command */ -void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, - int display, safi_t safi, json_object *json_paths) +void route_vty_out(struct vty *vty, struct prefix *p, + struct bgp_path_info *path, int display, safi_t safi, + json_object *json_paths) { struct attr *attr; json_object *json_path = NULL; @@ -6442,9 +6533,8 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, json_object *json_nexthop_global = NULL; json_object *json_nexthop_ll = NULL; char vrf_id_str[VRF_NAMSIZ] = {0}; - bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF) - ? true - : false; + bool nexthop_self = + CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false; bool nexthop_othervrf = false; vrf_id_t nexthop_vrfid = VRF_DEFAULT; const char *nexthop_vrfname = "Default"; @@ -6453,7 +6543,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, json_path = json_object_new_object(); /* short status lead text */ - route_vty_short_status_out(vty, binfo, json_path); + route_vty_short_status_out(vty, path, json_path); if (!json_paths) { /* print prefix and mask */ @@ -6466,7 +6556,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, } /* Print attribute */ - attr = binfo->attr; + attr = path->attr; if (!attr) { if (json_paths) json_object_array_add(json_paths, json_path); @@ -6480,26 +6570,26 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, * If vrf id of nexthop is different from that of prefix, * set up printable string to append */ - if (binfo->extra && binfo->extra->bgp_orig) { + if (path->extra && path->extra->bgp_orig) { const char *self = ""; if (nexthop_self) self = "<"; nexthop_othervrf = true; - nexthop_vrfid = binfo->extra->bgp_orig->vrf_id; + nexthop_vrfid = path->extra->bgp_orig->vrf_id; - if (binfo->extra->bgp_orig->vrf_id == VRF_UNKNOWN) + if (path->extra->bgp_orig->vrf_id == VRF_UNKNOWN) snprintf(vrf_id_str, sizeof(vrf_id_str), "@%s%s", VRFID_NONE_STR, self); else snprintf(vrf_id_str, sizeof(vrf_id_str), "@%u%s", - binfo->extra->bgp_orig->vrf_id, self); + path->extra->bgp_orig->vrf_id, self); - if (binfo->extra->bgp_orig->inst_type != - BGP_INSTANCE_TYPE_DEFAULT) + if (path->extra->bgp_orig->inst_type + != BGP_INSTANCE_TYPE_DEFAULT) - nexthop_vrfname = binfo->extra->bgp_orig->name; + nexthop_vrfname = path->extra->bgp_orig->name; } else { const char *self = ""; @@ -6626,7 +6716,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, /* We display both LL & GL if both have been * received */ if ((attr->mp_nexthop_len == 32) - || (binfo->peer->conf_if)) { + || (path->peer->conf_if)) { json_nexthop_ll = json_object_new_object(); json_object_string_add( json_nexthop_ll, "ip", @@ -6655,10 +6745,10 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, * prefer-global is set */ if (((attr->mp_nexthop_len == 32) && !attr->mp_nexthop_prefer_global) - || (binfo->peer->conf_if)) { - if (binfo->peer->conf_if) { + || (path->peer->conf_if)) { + if (path->peer->conf_if) { len = vty_out(vty, "%s", - binfo->peer->conf_if); + path->peer->conf_if); len = 16 - len; /* len of IPv6 addr + max len of def @@ -6741,7 +6831,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, char buf[BUFSIZ]; json_object_string_add( json_path, "peerId", - sockunion2str(&binfo->peer->su, buf, SU_ADDRSTRLEN)); + sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN)); } /* Print aspath */ @@ -6805,7 +6895,7 @@ void route_vty_out(struct vty *vty, struct prefix *p, struct bgp_info *binfo, /* prints an additional line, indented, with VNC info, if * present */ if ((safi == SAFI_MPLS_VPN) || (safi == SAFI_ENCAP)) - rfapi_vty_out_vncinfo(vty, p, binfo, safi); + rfapi_vty_out_vncinfo(vty, p, path, safi); #endif } } @@ -6834,9 +6924,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, json_net, "addrPrefix", inet_ntop(p->family, &p->u.prefix, buff, BUFSIZ)); json_object_int_add(json_net, "prefixLen", p->prefixlen); - sprintf(buf2, "%s/%d", - inet_ntop(p->family, &p->u.prefix, buff, - BUFSIZ), p->prefixlen); + prefix2str(p, buf2, PREFIX_STRLEN); json_object_string_add(json_net, "network", buf2); } else route_vty_out_route(p, vty, NULL); @@ -6863,7 +6951,7 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, char buf[BUFSIZ]; json_object_string_add( - json_net, "netHopGloabal", + json_net, "nextHopGlobal", inet_ntop(AF_INET6, &attr->mp_nexthop_global, buf, BUFSIZ)); @@ -6971,21 +7059,21 @@ void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, } void route_vty_out_tag(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, safi_t safi, + struct bgp_path_info *path, int display, safi_t safi, json_object *json) { json_object *json_out = NULL; struct attr *attr; mpls_label_t label = MPLS_INVALID_LABEL; - if (!binfo->extra) + if (!path->extra) return; if (json) json_out = json_object_new_object(); /* short status lead text */ - route_vty_short_status_out(vty, binfo, json_out); + route_vty_short_status_out(vty, path, json_out); /* print prefix and mask */ if (json == NULL) { @@ -6996,7 +7084,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p, } /* Print attribute */ - attr = binfo->attr; + attr = path->attr; if (attr) { if (((p->family == AF_INET) && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) @@ -7072,7 +7160,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p, } } - label = decode_label(&binfo->extra->label[0]); + label = decode_label(&path->extra->label[0]); if (bgp_is_valid_label(&label)) { if (json) { @@ -7086,7 +7174,7 @@ void route_vty_out_tag(struct vty *vty, struct prefix *p, } void route_vty_out_overlay(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, + struct bgp_path_info *path, int display, json_object *json_paths) { struct attr *attr; @@ -7096,11 +7184,11 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, if (json_paths) json_path = json_object_new_object(); - if (!binfo->extra) + if (!path->extra) return; /* short status lead text */ - route_vty_short_status_out(vty, binfo, json_path); + route_vty_short_status_out(vty, path, json_path); /* print prefix and mask */ if (!display) @@ -7109,7 +7197,7 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, vty_out(vty, "%*s", 17, " "); /* Print attribute */ - attr = binfo->attr; + attr = path->attr; if (attr) { char buf1[BUFSIZ]; int af = NEXTHOP_FAMILY(attr->mp_nexthop_len); @@ -7164,15 +7252,15 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, /* dampening route */ static void damp_route_vty_out(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, safi_t safi, - bool use_json, json_object *json) + struct bgp_path_info *path, int display, + safi_t safi, bool use_json, json_object *json) { struct attr *attr; int len; char timebuf[BGP_UPTIME_LEN]; /* short status lead text */ - route_vty_short_status_out(vty, binfo, json); + route_vty_short_status_out(vty, path, json); /* print prefix and mask */ if (!use_json) { @@ -7182,7 +7270,7 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, vty_out(vty, "%*s", 17, " "); } - len = vty_out(vty, "%s", binfo->peer->host); + len = vty_out(vty, "%s", path->peer->host); len = 17 - len; if (len < 1) { if (!use_json) @@ -7195,15 +7283,16 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, } if (use_json) - bgp_damp_reuse_time_vty(vty, binfo, timebuf, BGP_UPTIME_LEN, + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, use_json, json); else - vty_out(vty, "%s ", bgp_damp_reuse_time_vty(vty, binfo, timebuf, - BGP_UPTIME_LEN, - use_json, json)); + vty_out(vty, "%s ", + bgp_damp_reuse_time_vty(vty, path, timebuf, + BGP_UPTIME_LEN, use_json, + json)); /* Print attribute */ - attr = binfo->attr; + attr = path->attr; if (attr) { /* Print aspath */ if (attr->aspath) { @@ -7227,21 +7316,21 @@ static void damp_route_vty_out(struct vty *vty, struct prefix *p, /* flap route */ static void flap_route_vty_out(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, safi_t safi, - bool use_json, json_object *json) + struct bgp_path_info *path, int display, + safi_t safi, bool use_json, json_object *json) { struct attr *attr; struct bgp_damp_info *bdi; char timebuf[BGP_UPTIME_LEN]; int len; - if (!binfo->extra) + if (!path->extra) return; - bdi = binfo->extra->damp_info; + bdi = path->extra->damp_info; /* short status lead text */ - route_vty_short_status_out(vty, binfo, json); + route_vty_short_status_out(vty, path, json); /* print prefix and mask */ if (!use_json) { @@ -7251,7 +7340,7 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p, vty_out(vty, "%*s", 17, " "); } - len = vty_out(vty, "%s", binfo->peer->host); + len = vty_out(vty, "%s", path->peer->host); len = 16 - len; if (len < 1) { if (!use_json) @@ -7282,14 +7371,14 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p, vty_out(vty, "%s ", peer_uptime(bdi->start_time, timebuf, BGP_UPTIME_LEN, 0, NULL)); - if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED) - && !CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED) + && !CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { if (use_json) - bgp_damp_reuse_time_vty(vty, binfo, timebuf, + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, use_json, json); else vty_out(vty, "%s ", - bgp_damp_reuse_time_vty(vty, binfo, timebuf, + bgp_damp_reuse_time_vty(vty, path, timebuf, BGP_UPTIME_LEN, use_json, json)); } else { @@ -7298,7 +7387,7 @@ static void flap_route_vty_out(struct vty *vty, struct prefix *p, } /* Print attribute */ - attr = binfo->attr; + attr = path->attr; if (attr) { /* Print aspath */ if (attr->aspath) { @@ -7375,7 +7464,7 @@ static void route_vty_out_advertised_to(struct vty *vty, struct peer *peer, } void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, - struct bgp_info *binfo, afi_t afi, safi_t safi, + struct bgp_path_info *path, afi_t afi, safi_t safi, json_object *json_paths) { char buf[INET6_ADDRSTRLEN]; @@ -7403,9 +7492,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, int addpath_capable; int has_adj; unsigned int first_as; - bool nexthop_self = CHECK_FLAG(binfo->flags, BGP_INFO_ANNC_NH_SELF) - ? true - : false; + bool nexthop_self = + CHECK_FLAG(path->flags, BGP_PATH_ANNC_NH_SELF) ? true : false; if (json_paths) { json_path = json_object_new_object(); @@ -7419,18 +7507,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, bgp_evpn_route2str((struct prefix_evpn *)p, buf2, sizeof(buf2)); vty_out(vty, " Route %s", buf2); tag_buf[0] = '\0'; - if (binfo->extra && binfo->extra->num_labels) { - bgp_evpn_label2str(binfo->extra->label, - binfo->extra->num_labels, tag_buf, + if (path->extra && path->extra->num_labels) { + bgp_evpn_label2str(path->extra->label, + path->extra->num_labels, tag_buf, sizeof(tag_buf)); vty_out(vty, " VNI %s", tag_buf); } vty_out(vty, "\n"); - if (binfo->extra && binfo->extra->parent) { - struct bgp_info *parent_ri; + if (path->extra && path->extra->parent) { + struct bgp_path_info *parent_ri; struct bgp_node *rn, *prn; - parent_ri = (struct bgp_info *)binfo->extra->parent; + parent_ri = (struct bgp_path_info *)path->extra->parent; rn = parent_ri->net; if (rn && rn->prn) { prn = rn->prn; @@ -7443,7 +7531,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } } - attr = binfo->attr; + attr = path->attr; if (attr) { /* Line1 display AS-path, Aggregator */ @@ -7463,7 +7551,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } } - if (CHECK_FLAG(binfo->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED)) { if (json_paths) json_object_boolean_true_add(json_path, "removed"); @@ -7471,7 +7559,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", (removed)"); } - if (CHECK_FLAG(binfo->flags, BGP_INFO_STALE)) { + if (CHECK_FLAG(path->flags, BGP_PATH_STALE)) { if (json_paths) json_object_boolean_true_add(json_path, "stale"); @@ -7494,7 +7582,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } } - if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], + if (CHECK_FLAG(path->peer->af_flags[afi][safi], PEER_FLAG_REFLECTOR_CLIENT)) { if (json_paths) json_object_boolean_true_add( @@ -7503,7 +7591,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", (Received from a RR-client)"); } - if (CHECK_FLAG(binfo->peer->af_flags[afi][safi], + if (CHECK_FLAG(path->peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT)) { if (json_paths) json_object_boolean_true_add( @@ -7512,13 +7600,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", (Received from a RS-client)"); } - if (CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { if (json_paths) json_object_boolean_true_add( json_path, "dampeningHistoryEntry"); else vty_out(vty, ", (history entry)"); - } else if (CHECK_FLAG(binfo->flags, BGP_INFO_DAMPED)) { + } else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)) { if (json_paths) json_object_boolean_true_add( json_path, "dampeningSuppressed"); @@ -7580,21 +7668,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } /* Display the IGP cost or 'inaccessible' */ - if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { + if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) { if (json_paths) json_object_boolean_false_add( json_nexthop_global, "accessible"); else vty_out(vty, " (inaccessible)"); } else { - if (binfo->extra && binfo->extra->igpmetric) { + if (path->extra && path->extra->igpmetric) { if (json_paths) json_object_int_add( json_nexthop_global, "metric", - binfo->extra->igpmetric); + path->extra->igpmetric); else vty_out(vty, " (metric %u)", - binfo->extra->igpmetric); + path->extra->igpmetric); } /* IGP cost is 0, display this only for json */ @@ -7611,7 +7699,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, /* Display peer "from" output */ /* This path was originated locally */ - if (binfo->peer == bgp->peer_self) { + if (path->peer == bgp->peer_self) { if (safi == SAFI_EVPN || (p->family == AF_INET @@ -7643,53 +7731,52 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, if (json_paths) { json_object_string_add( json_peer, "peerId", - sockunion2str(&binfo->peer->su, buf, + sockunion2str(&path->peer->su, buf, SU_ADDRSTRLEN)); json_object_string_add( json_peer, "routerId", inet_ntop(AF_INET, - &binfo->peer->remote_id, buf1, + &path->peer->remote_id, buf1, sizeof(buf1))); - if (binfo->peer->hostname) + if (path->peer->hostname) json_object_string_add( json_peer, "hostname", - binfo->peer->hostname); + path->peer->hostname); - if (binfo->peer->domainname) + if (path->peer->domainname) json_object_string_add( json_peer, "domainname", - binfo->peer->domainname); + path->peer->domainname); - if (binfo->peer->conf_if) + if (path->peer->conf_if) json_object_string_add( json_peer, "interface", - binfo->peer->conf_if); + path->peer->conf_if); } else { - if (binfo->peer->conf_if) { - if (binfo->peer->hostname + if (path->peer->conf_if) { + if (path->peer->hostname && bgp_flag_check( - binfo->peer->bgp, + path->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) vty_out(vty, " from %s(%s)", - binfo->peer->hostname, - binfo->peer->conf_if); + path->peer->hostname, + path->peer->conf_if); else vty_out(vty, " from %s", - binfo->peer->conf_if); + path->peer->conf_if); } else { - if (binfo->peer->hostname + if (path->peer->hostname && bgp_flag_check( - binfo->peer->bgp, + path->peer->bgp, BGP_FLAG_SHOW_HOSTNAME)) vty_out(vty, " from %s(%s)", - binfo->peer->hostname, - binfo->peer->host); + path->peer->hostname, + path->peer->host); else vty_out(vty, " from %s", sockunion2str( - &binfo->peer - ->su, + &path->peer->su, buf, SU_ADDRSTRLEN)); } @@ -7702,7 +7789,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, " (%s)", inet_ntop( AF_INET, - &binfo->peer->remote_id, + &path->peer->remote_id, buf1, sizeof(buf1))); } } @@ -7710,18 +7797,18 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, /* * Note when vrfid of nexthop is different from that of prefix */ - if (binfo->extra && binfo->extra->bgp_orig) { - vrf_id_t nexthop_vrfid = binfo->extra->bgp_orig->vrf_id; + if (path->extra && path->extra->bgp_orig) { + vrf_id_t nexthop_vrfid = path->extra->bgp_orig->vrf_id; if (json_paths) { const char *vn; - if (binfo->extra->bgp_orig->inst_type == - BGP_INSTANCE_TYPE_DEFAULT) + if (path->extra->bgp_orig->inst_type + == BGP_INSTANCE_TYPE_DEFAULT) vn = "Default"; else - vn = binfo->extra->bgp_orig->name; + vn = path->extra->bgp_orig->name; json_object_string_add(json_path, "nhVrfName", vn); @@ -7846,13 +7933,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, attr->tag); } - if (!CHECK_FLAG(binfo->flags, BGP_INFO_VALID)) { + if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) { if (json_paths) json_object_boolean_false_add(json_path, "valid"); else vty_out(vty, ", invalid"); - } else if (!CHECK_FLAG(binfo->flags, BGP_INFO_HISTORY)) { + } else if (!CHECK_FLAG(path->flags, BGP_PATH_HISTORY)) { if (json_paths) json_object_boolean_true_add(json_path, "valid"); @@ -7860,8 +7947,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", valid"); } - if (binfo->peer != bgp->peer_self) { - if (binfo->peer->as == binfo->peer->local_as) { + if (path->peer != bgp->peer_self) { + if (path->peer->as == path->peer->local_as) { if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) { if (json_paths) @@ -7881,7 +7968,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } } else { if (bgp_confederation_peers_check( - bgp, binfo->peer->as)) { + bgp, path->peer->as)) { if (json_paths) json_object_string_add( json_peer, "type", @@ -7898,7 +7985,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", external"); } } - } else if (binfo->sub_type == BGP_ROUTE_AGGREGATE) { + } else if (path->sub_type == BGP_ROUTE_AGGREGATE) { if (json_paths) { json_object_boolean_true_add(json_path, "aggregated"); @@ -7907,7 +7994,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } else { vty_out(vty, ", aggregated, local"); } - } else if (binfo->type != ZEBRA_ROUTE_BGP) { + } else if (path->type != ZEBRA_ROUTE_BGP) { if (json_paths) json_object_boolean_true_add(json_path, "sourced"); @@ -7932,9 +8019,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, ", atomic-aggregate"); } - if (CHECK_FLAG(binfo->flags, BGP_INFO_MULTIPATH) - || (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED) - && bgp_info_mpath_count(binfo))) { + if (CHECK_FLAG(path->flags, BGP_PATH_MULTIPATH) + || (CHECK_FLAG(path->flags, BGP_PATH_SELECTED) + && bgp_path_info_mpath_count(path))) { if (json_paths) json_object_boolean_true_add(json_path, "multipath"); @@ -7943,7 +8030,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } // Mark the bestpath(s) - if (CHECK_FLAG(binfo->flags, BGP_INFO_DMED_SELECTED)) { + if (CHECK_FLAG(path->flags, BGP_PATH_DMED_SELECTED)) { first_as = aspath_get_first_as(attr->aspath); if (json_paths) { @@ -7962,7 +8049,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } } - if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) { if (json_paths) { if (!json_bestpath) json_bestpath = @@ -8092,14 +8179,14 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, vty_out(vty, "\n"); } - if (binfo->extra && binfo->extra->damp_info) - bgp_damp_info_vty(vty, binfo, json_path); + if (path->extra && path->extra->damp_info) + bgp_damp_info_vty(vty, path, json_path); /* Remote Label */ - if (binfo->extra && bgp_is_valid_label(&binfo->extra->label[0]) + if (path->extra && bgp_is_valid_label(&path->extra->label[0]) && safi != SAFI_EVPN) { - mpls_label_t label = - label_pton(&binfo->extra->label[0]); + mpls_label_t label = label_pton(&path->extra->label[0]); + if (json_paths) json_object_int_add(json_path, "remoteLabel", label); @@ -8118,16 +8205,16 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } /* Line 8 display Addpath IDs */ - if (binfo->addpath_rx_id || binfo->addpath_tx_id) { + if (path->addpath_rx_id || path->addpath_tx_id) { if (json_paths) { json_object_int_add(json_path, "addpathRxId", - binfo->addpath_rx_id); + path->addpath_rx_id); json_object_int_add(json_path, "addpathTxId", - binfo->addpath_tx_id); + path->addpath_tx_id); } else { vty_out(vty, " AddPath ID: RX %u, TX %u\n", - binfo->addpath_rx_id, - binfo->addpath_tx_id); + path->addpath_rx_id, + path->addpath_tx_id); } } @@ -8140,12 +8227,12 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, addpath_capable = bgp_addpath_encode_tx(peer, afi, safi); has_adj = bgp_adj_out_lookup( - peer, binfo->net, binfo->addpath_tx_id); + peer, path->net, path->addpath_tx_id); if ((addpath_capable && has_adj) || (!addpath_capable && has_adj - && CHECK_FLAG(binfo->flags, - BGP_INFO_SELECTED))) { + && CHECK_FLAG(path->flags, + BGP_PATH_SELECTED))) { if (json_path && !json_adv_to) json_adv_to = json_object_new_object(); @@ -8171,7 +8258,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct prefix *p, } /* Line 9 display Uptime */ - tbuf = time(NULL) - (bgp_clock() - binfo->uptime); + tbuf = time(NULL) - (bgp_clock() - path->uptime); if (json_paths) { json_last_update = json_object_new_object(); json_object_int_add(json_last_update, "epoch", tbuf); @@ -8259,14 +8346,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, unsigned long *total_cum, unsigned long *json_header_depth) { - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_node *rn; int header = 1; int display; unsigned long output_count = 0; unsigned long total_count = 0; struct prefix *p; - char buf[BUFSIZ]; char buf2[BUFSIZ]; json_object *json_paths = NULL; int first = 1; @@ -8304,19 +8390,19 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, else json_paths = NULL; - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { total_count++; if (type == bgp_show_type_flap_statistics || type == bgp_show_type_flap_neighbor || type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) { - if (!(ri->extra && ri->extra->damp_info)) + if (!(pi->extra && pi->extra->damp_info)) continue; } if (type == bgp_show_type_regexp) { regex_t *regex = output_arg; - if (bgp_regexec(regex, ri->attr->aspath) + if (bgp_regexec(regex, pi->attr->aspath) == REG_NOMATCH) continue; } @@ -8330,23 +8416,23 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, if (type == bgp_show_type_filter_list) { struct as_list *as_list = output_arg; - if (as_list_apply(as_list, ri->attr->aspath) + if (as_list_apply(as_list, pi->attr->aspath) != AS_FILTER_PERMIT) continue; } if (type == bgp_show_type_route_map) { struct route_map *rmap = output_arg; - struct bgp_info binfo; + struct bgp_path_info path; struct attr dummy_attr; int ret; - bgp_attr_dup(&dummy_attr, ri->attr); + bgp_attr_dup(&dummy_attr, pi->attr); - binfo.peer = ri->peer; - binfo.attr = &dummy_attr; + path.peer = pi->peer; + path.attr = &dummy_attr; ret = route_map_apply(rmap, &rn->p, RMAP_BGP, - &binfo); + &path); if (ret == RMAP_DENYMATCH) continue; } @@ -8355,9 +8441,9 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, || type == bgp_show_type_damp_neighbor) { union sockunion *su = output_arg; - if (ri->peer == NULL - || ri->peer->su_remote == NULL - || !sockunion_same(ri->peer->su_remote, su)) + if (pi->peer == NULL + || pi->peer->su_remote == NULL + || !sockunion_same(pi->peer->su_remote, su)) continue; } if (type == bgp_show_type_cidr_only) { @@ -8380,28 +8466,28 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, continue; } if (type == bgp_show_type_community_all) { - if (!ri->attr->community) + if (!pi->attr->community) continue; } if (type == bgp_show_type_community) { struct community *com = output_arg; - if (!ri->attr->community - || !community_match(ri->attr->community, + if (!pi->attr->community + || !community_match(pi->attr->community, com)) continue; } if (type == bgp_show_type_community_exact) { struct community *com = output_arg; - if (!ri->attr->community - || !community_cmp(ri->attr->community, com)) + if (!pi->attr->community + || !community_cmp(pi->attr->community, com)) continue; } if (type == bgp_show_type_community_list) { struct community_list *list = output_arg; - if (!community_list_match(ri->attr->community, + if (!community_list_match(pi->attr->community, list)) continue; } @@ -8409,32 +8495,32 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, struct community_list *list = output_arg; if (!community_list_exact_match( - ri->attr->community, list)) + pi->attr->community, list)) continue; } if (type == bgp_show_type_lcommunity) { struct lcommunity *lcom = output_arg; - if (!ri->attr->lcommunity - || !lcommunity_match(ri->attr->lcommunity, + if (!pi->attr->lcommunity + || !lcommunity_match(pi->attr->lcommunity, lcom)) continue; } if (type == bgp_show_type_lcommunity_list) { struct community_list *list = output_arg; - if (!lcommunity_list_match(ri->attr->lcommunity, + if (!lcommunity_list_match(pi->attr->lcommunity, list)) continue; } if (type == bgp_show_type_lcommunity_all) { - if (!ri->attr->lcommunity) + if (!pi->attr->lcommunity) continue; } if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) { - if (!CHECK_FLAG(ri->flags, BGP_INFO_DAMPED) - || CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + if (!CHECK_FLAG(pi->flags, BGP_PATH_DAMPED) + || CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) continue; } @@ -8469,14 +8555,14 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, } if (type == bgp_show_type_dampend_paths || type == bgp_show_type_damp_neighbor) - damp_route_vty_out(vty, &rn->p, ri, display, + damp_route_vty_out(vty, &rn->p, pi, display, safi, use_json, json_paths); else if (type == bgp_show_type_flap_statistics || type == bgp_show_type_flap_neighbor) - flap_route_vty_out(vty, &rn->p, ri, display, + flap_route_vty_out(vty, &rn->p, pi, display, safi, use_json, json_paths); else - route_vty_out(vty, &rn->p, ri, display, safi, + route_vty_out(vty, &rn->p, pi, display, safi, json_paths); display++; } @@ -8487,14 +8573,32 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi, continue; p = &rn->p; - sprintf(buf2, "%s/%d", - inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), - p->prefixlen); - if (first) - vty_out(vty, "\"%s\": ", buf2); - else - vty_out(vty, ",\"%s\": ", buf2); + /* encode prefix */ + if (p->family == AF_FLOWSPEC) { + char retstr[BGP_FLOWSPEC_STRING_DISPLAY_MAX]; + bgp_fs_nlri_get_string((unsigned char *) + p->u.prefix_flowspec.ptr, + p->u.prefix_flowspec + .prefixlen, + retstr, + NLRI_STRING_FORMAT_MIN, + NULL); + if (first) + vty_out(vty, "\"%s/%d\": ", + retstr, + p->u.prefix_flowspec.prefixlen); + else + vty_out(vty, ",\"%s/%d\": ", + retstr, + p->u.prefix_flowspec.prefixlen); + } else { + prefix2str(p, buf2, sizeof(buf2)); + if (first) + vty_out(vty, "\"%s\": ", buf2); + else + vty_out(vty, ",\"%s\": ", buf2); + } vty_out(vty, "%s", json_object_to_json_string(json_paths)); json_object_free(json_paths); @@ -8661,7 +8765,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, struct bgp_node *rn, struct prefix_rd *prd, afi_t afi, safi_t safi, json_object *json) { - struct bgp_info *ri; + struct bgp_path_info *pi; struct prefix *p; struct peer *peer; struct listnode *node, *nnode; @@ -8728,23 +8832,45 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, vty_out(vty, "not allocated\n"); } - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { count++; - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) { best = count; - if (ri->extra && ri->extra->suppress) + if (pi->extra && pi->extra->suppress) suppress = 1; - if (ri->attr->community != NULL) { - if (community_include(ri->attr->community, - COMMUNITY_NO_ADVERTISE)) - no_advertise = 1; - if (community_include(ri->attr->community, - COMMUNITY_NO_EXPORT)) - no_export = 1; - if (community_include(ri->attr->community, - COMMUNITY_LOCAL_AS)) - local_as = 1; - } + + if (pi->attr->community == NULL) + continue; + + no_advertise += community_include( + pi->attr->community, COMMUNITY_NO_ADVERTISE); + no_export += community_include(pi->attr->community, + COMMUNITY_NO_EXPORT); + local_as += community_include(pi->attr->community, + COMMUNITY_LOCAL_AS); + accept_own += community_include(pi->attr->community, + COMMUNITY_ACCEPT_OWN); + route_filter_translated_v4 += community_include( + pi->attr->community, + COMMUNITY_ROUTE_FILTER_TRANSLATED_v4); + route_filter_translated_v6 += community_include( + pi->attr->community, + COMMUNITY_ROUTE_FILTER_TRANSLATED_v6); + route_filter_v4 += community_include( + pi->attr->community, COMMUNITY_ROUTE_FILTER_v4); + route_filter_v6 += community_include( + pi->attr->community, COMMUNITY_ROUTE_FILTER_v6); + llgr_stale += community_include(pi->attr->community, + COMMUNITY_LLGR_STALE); + no_llgr += community_include(pi->attr->community, + COMMUNITY_NO_LLGR); + accept_own_nexthop += + community_include(pi->attr->community, + COMMUNITY_ACCEPT_OWN_NEXTHOP); + blackhole += community_include(pi->attr->community, + COMMUNITY_BLACKHOLE); + no_peer += community_include(pi->attr->community, + COMMUNITY_NO_PEER); } } @@ -8847,7 +8973,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, struct prefix match; struct bgp_node *rn; struct bgp_node *rm; - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_table *table; json_object *json = NULL; json_object *json_paths = NULL; @@ -8885,7 +9011,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, continue; } - for (ri = rm->info; ri; ri = ri->next) { + for (pi = rm->info; pi; pi = pi->next) { if (header) { route_vty_out_detail_header( vty, bgp, rm, @@ -8895,17 +9021,17 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, } display++; - if (pathtype == BGP_PATH_ALL - || (pathtype == BGP_PATH_BESTPATH - && CHECK_FLAG(ri->flags, - BGP_INFO_SELECTED)) - || (pathtype == BGP_PATH_MULTIPATH - && (CHECK_FLAG(ri->flags, - BGP_INFO_MULTIPATH) - || CHECK_FLAG(ri->flags, - BGP_INFO_SELECTED)))) + if (pathtype == BGP_PATH_SHOW_ALL + || (pathtype == BGP_PATH_SHOW_BESTPATH + && CHECK_FLAG(pi->flags, + BGP_PATH_SELECTED)) + || (pathtype == BGP_PATH_SHOW_MULTIPATH + && (CHECK_FLAG(pi->flags, + BGP_PATH_MULTIPATH) + || CHECK_FLAG(pi->flags, + BGP_PATH_SELECTED)))) route_vty_out_detail(vty, bgp, &rm->p, - ri, AFI_IP, safi, + pi, AFI_IP, safi, json_paths); } @@ -8923,7 +9049,7 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, if ((rn = bgp_node_match(rib, &match)) != NULL) { if (!prefix_check || rn->p.prefixlen == match.prefixlen) { - for (ri = rn->info; ri; ri = ri->next) { + for (pi = rn->info; pi; pi = pi->next) { if (header) { route_vty_out_detail_header( vty, bgp, rn, NULL, afi, @@ -8932,20 +9058,22 @@ static int bgp_show_route_in_table(struct vty *vty, struct bgp *bgp, } display++; - if (pathtype == BGP_PATH_ALL - || (pathtype == BGP_PATH_BESTPATH + if (pathtype == BGP_PATH_SHOW_ALL + || (pathtype + == BGP_PATH_SHOW_BESTPATH && CHECK_FLAG( - ri->flags, - BGP_INFO_SELECTED)) - || (pathtype == BGP_PATH_MULTIPATH + pi->flags, + BGP_PATH_SELECTED)) + || (pathtype + == BGP_PATH_SHOW_MULTIPATH && (CHECK_FLAG( - ri->flags, - BGP_INFO_MULTIPATH) + pi->flags, + BGP_PATH_MULTIPATH) || CHECK_FLAG( - ri->flags, - BGP_INFO_SELECTED)))) + pi->flags, + BGP_PATH_SELECTED)))) route_vty_out_detail( - vty, bgp, &rn->p, ri, + vty, bgp, &rn->p, pi, afi, safi, json_paths); } } @@ -9155,10 +9283,6 @@ DEFUN (show_ip_bgp, |prefix-list WORD\ |filter-list WORD\ |statistics\ - |community [exact-match]\ |community-list <(1-500)|WORD> [exact-match]\ |A.B.C.D/M longer-prefixes\ |X:X::X:X/M longer-prefixes\ @@ -9178,23 +9302,6 @@ DEFUN (show_ip_bgp, "Display routes conforming to the filter-list\n" "Regular expression access list name\n" "BGP RIB advertisement statistics\n" - "Display routes matching the communities\n" - COMMUNITY_AANN_STR - "Do not send outside local AS (well-known community)\n" - "Do not advertise to any peer (well-known community)\n" - "Do not export to next AS (well-known community)\n" - "Graceful shutdown (well-known community)\n" - "Do not export to any peer (well-known community)\n" - "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n" - "Staled Long-lived Graceful Restart VPN route (well-known community)\n" - "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n" - "Should accept local VPN route if exported and imported into different VRF (well-known community)\n" - "Should accept VPN route with local nexthop (well-known community)\n" - "RT VPNv6 route filtering (well-known community)\n" - "RT VPNv4 route filtering (well-known community)\n" - "RT translated VPNv6 route filtering (well-known community)\n" - "RT translated VPNv4 route filtering (well-known community)\n" - "Exact match of the communities\n" "Display routes matching the community-list\n" "community-list number\n" "community-list name\n" @@ -9256,11 +9363,14 @@ DEFUN (show_ip_bgp, DEFUN (show_ip_bgp_json, show_ip_bgp_json_cmd, "show [ip] bgp [ VIEWVRFNAME] ["BGP_AFI_CMD_STR" ["BGP_SAFI_WITH_LABEL_CMD_STR"]]\ - [<\ - cidr-only\ - |dampening \ - |community [] [exact-match]\ - >] [json]", + [cidr-only\ + |dampening \ + |community [AA:NN|local-AS|no-advertise|no-export\ + |graceful-shutdown|no-peer|blackhole|llgr-stale|no-llgr\ + |accept-own|accept-own-nexthop|route-filter-v6\ + |route-filter-v4|route-filter-translated-v6\ + |route-filter-translated-v4] [exact-match]\ + ] [json]", SHOW_STR IP_STR BGP_STR @@ -9277,6 +9387,16 @@ DEFUN (show_ip_bgp_json, "Do not advertise to any peer (well-known community)\n" "Do not export to next AS (well-known community)\n" "Graceful shutdown (well-known community)\n" + "Do not export to any peer (well-known community)\n" + "Inform EBGP peers to blackhole traffic to prefix (well-known community)\n" + "Staled Long-lived Graceful Restart VPN route (well-known community)\n" + "Removed because Long-lived Graceful Restart was not enabled for VPN route (well-known community)\n" + "Should accept local VPN route if exported and imported into different VRF (well-known community)\n" + "Should accept VPN route with local nexthop (well-known community)\n" + "RT VPNv6 route filtering (well-known community)\n" + "RT VPNv4 route filtering (well-known community)\n" + "RT translated VPNv6 route filtering (well-known community)\n" + "RT translated VPNv4 route filtering (well-known community)\n" "Exact match of the communities\n" JSON_STR) { @@ -9285,7 +9405,6 @@ DEFUN (show_ip_bgp_json, enum bgp_show_type sh_type = bgp_show_type_normal; struct bgp *bgp = NULL; int idx = 0; - int idx_community_type = 0; int exact_match = 0; bool uj = use_json(argc, argv); @@ -9312,29 +9431,23 @@ DEFUN (show_ip_bgp_json, } if (argv_find(argv, argc, "community", &idx)) { + char *maybecomm = idx + 1 < argc ? argv[idx + 1]->text : NULL; + char *community = NULL; - /* show a specific community */ - if (argv_find(argv, argc, "local-AS", &idx_community_type) || - argv_find(argv, argc, "no-advertise", - &idx_community_type) || - argv_find(argv, argc, "no-export", - &idx_community_type) || - argv_find(argv, argc, "graceful-shutdown", - &idx_community_type) || - argv_find(argv, argc, "AA:NN", &idx_community_type)) { - if (argv_find(argv, argc, "exact-match", &idx)) - exact_match = 1; + if (maybecomm && !strmatch(maybecomm, "json") + && !strmatch(maybecomm, "exact-match")) + community = maybecomm; - return (bgp_show_community(vty, bgp, - argv[idx_community_type]->arg, - exact_match, afi, safi, uj)); - } else { + if (argv_find(argv, argc, "exact-match", &idx)) + exact_match = 1; - /* show all communities */ + if (community) + return bgp_show_community(vty, bgp, community, + exact_match, afi, safi, uj); + else return (bgp_show(vty, bgp, afi, safi, - bgp_show_type_community_all, NULL, - uj)); - } + bgp_show_type_community_all, NULL, + uj)); } return bgp_show(vty, bgp, afi, safi, sh_type, NULL, uj); @@ -9405,11 +9518,11 @@ DEFUN (show_ip_bgp_route, /* [] */ if (argv_find(argv, argc, "bestpath", &idx)) - path_type = BGP_PATH_BESTPATH; + path_type = BGP_PATH_SHOW_BESTPATH; else if (argv_find(argv, argc, "multipath", &idx)) - path_type = BGP_PATH_MULTIPATH; + path_type = BGP_PATH_SHOW_MULTIPATH; else - path_type = BGP_PATH_ALL; + path_type = BGP_PATH_SHOW_ALL; return bgp_show_route(vty, bgp, prefix, afi, safi, NULL, prefix_check, path_type, uj); @@ -9558,7 +9671,7 @@ static int bgp_show_community(struct vty *vty, struct bgp *bgp, (exact ? bgp_show_type_community_exact : bgp_show_type_community), com, use_json); - community_free(com); + community_free(&com); return ret; } @@ -9738,9 +9851,9 @@ static int bgp_table_stats_walker(struct thread *t) ts->counts[BGP_STATS_MAXBITLEN] = space; for (rn = top; rn; rn = bgp_route_next(rn)) { - struct bgp_info *ri; + struct bgp_path_info *pi; struct bgp_node *prn = bgp_node_parent_nolock(rn); - unsigned int rinum = 0; + unsigned int pinum = 0; if (rn == top) continue; @@ -9771,23 +9884,23 @@ static int bgp_table_stats_walker(struct thread *t) } else if (prn->info) ts->counts[BGP_STATS_MAX_AGGREGATEABLE]++; - for (ri = rn->info; ri; ri = ri->next) { - rinum++; + for (pi = rn->info; pi; pi = pi->next) { + pinum++; ts->counts[BGP_STATS_RIB]++; - if (ri->attr - && (CHECK_FLAG(ri->attr->flag, + if (pi->attr + && (CHECK_FLAG(pi->attr->flag, ATTR_FLAG_BIT( BGP_ATTR_ATOMIC_AGGREGATE)))) ts->counts[BGP_STATS_AGGREGATES]++; /* as-path stats */ - if (ri->attr && ri->attr->aspath) { + if (pi->attr && pi->attr->aspath) { unsigned int hops = - aspath_count_hops(ri->attr->aspath); + aspath_count_hops(pi->attr->aspath); unsigned int size = - aspath_size(ri->attr->aspath); - as_t highest = aspath_highest(ri->attr->aspath); + aspath_size(pi->attr->aspath); + as_t highest = aspath_highest(pi->attr->aspath); ts->counts[BGP_STATS_ASPATH_COUNT]++; @@ -9948,39 +10061,39 @@ static int bgp_peer_count_walker(struct thread *t) for (rn = bgp_table_top(pc->table); rn; rn = bgp_route_next(rn)) { struct bgp_adj_in *ain; - struct bgp_info *ri; + struct bgp_path_info *pi; for (ain = rn->adj_in; ain; ain = ain->next) if (ain->peer == peer) pc->count[PCOUNT_ADJ_IN]++; - for (ri = rn->info; ri; ri = ri->next) { - if (ri->peer != peer) + for (pi = rn->info; pi; pi = pi->next) { + if (pi->peer != peer) continue; pc->count[PCOUNT_ALL]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_DAMPED)) + if (CHECK_FLAG(pi->flags, BGP_PATH_DAMPED)) pc->count[PCOUNT_DAMPED]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_HISTORY)) + if (CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) pc->count[PCOUNT_HISTORY]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) pc->count[PCOUNT_REMOVED]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_STALE)) + if (CHECK_FLAG(pi->flags, BGP_PATH_STALE)) pc->count[PCOUNT_STALE]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_VALID)) + if (CHECK_FLAG(pi->flags, BGP_PATH_VALID)) pc->count[PCOUNT_VALID]++; - if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) pc->count[PCOUNT_PFCNT]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_COUNTED)) { + if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) { pc->count[PCOUNT_COUNTED]++; - if (CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + if (CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) flog_err( EC_LIB_DEVELOPMENT, "Attempting to count but flags say it is unusable"); } else { - if (!CHECK_FLAG(ri->flags, BGP_INFO_UNUSEABLE)) + if (!CHECK_FLAG(pi->flags, BGP_PATH_UNUSEABLE)) flog_err( EC_LIB_DEVELOPMENT, "Not counted but flags say we should"); @@ -10176,7 +10289,7 @@ DEFUN (show_ip_bgp_vpn_all_route_prefix, } return bgp_show_route(vty, bgp, network, AFI_IP, SAFI_MPLS_VPN, NULL, 0, - BGP_PATH_ALL, use_json(argc, argv)); + BGP_PATH_SHOW_ALL, use_json(argc, argv)); } #endif /* KEEP_OLD_VPN_COMMANDS */ @@ -10205,7 +10318,7 @@ DEFUN (show_ip_bgp_l2vpn_evpn_all_route_prefix, return CMD_WARNING; } return bgp_show_route(vty, NULL, network, AFI_L2VPN, SAFI_EVPN, NULL, 0, - BGP_PATH_ALL, use_json(argc, argv)); + BGP_PATH_SHOW_ALL, use_json(argc, argv)); } static void show_adj_route(struct vty *vty, struct peer *peer, afi_t afi, @@ -10818,7 +10931,7 @@ DEFUN (show_bgp_afi_vpn_rd_route, } return bgp_show_route(vty, NULL, argv[6]->arg, afi, SAFI_MPLS_VPN, &prd, - 0, BGP_PATH_ALL, use_json(argc, argv)); + 0, BGP_PATH_SHOW_ALL, use_json(argc, argv)); } static struct bgp_distance *bgp_distance_new(void) @@ -10925,8 +11038,8 @@ static int bgp_distance_unset(struct vty *vty, const char *distance_str, } /* Apply BGP information to distance method. */ -uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, - safi_t safi, struct bgp *bgp) +uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *pinfo, + afi_t afi, safi_t safi, struct bgp *bgp) { struct bgp_node *rn; struct prefix q; @@ -10938,7 +11051,7 @@ uint8_t bgp_distance_apply(struct prefix *p, struct bgp_info *rinfo, afi_t afi, if (!bgp) return 0; - peer = rinfo->peer; + peer = pinfo->peer; /* Check source address. */ sockunion2hostprefix(&peer->su, &q); @@ -11204,8 +11317,8 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, struct prefix match; struct bgp_node *rn; struct bgp_node *rm; - struct bgp_info *ri; - struct bgp_info *ri_temp; + struct bgp_path_info *pi; + struct bgp_path_info *pi_temp; struct bgp *bgp; struct bgp_table *table; @@ -11247,16 +11360,16 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, if (!prefix_check || rm->p.prefixlen == match.prefixlen) { - ri = rm->info; - while (ri) { - if (ri->extra && ri->extra->damp_info) { - ri_temp = ri->next; + pi = rm->info; + while (pi) { + if (pi->extra && pi->extra->damp_info) { + pi_temp = pi->next; bgp_damp_info_free( - ri->extra->damp_info, + pi->extra->damp_info, 1); - ri = ri_temp; + pi = pi_temp; } else - ri = ri->next; + pi = pi->next; } } @@ -11267,16 +11380,16 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name, != NULL) { if (!prefix_check || rn->p.prefixlen == match.prefixlen) { - ri = rn->info; - while (ri) { - if (ri->extra && ri->extra->damp_info) { - ri_temp = ri->next; + pi = rn->info; + while (pi) { + if (pi->extra && pi->extra->damp_info) { + pi_temp = pi->next; bgp_damp_info_free( - ri->extra->damp_info, + pi->extra->damp_info, 1); - ri = ri_temp; + pi = pi_temp; } else - ri = ri->next; + pi = pi->next; } } @@ -11353,6 +11466,36 @@ DEFUN (clear_ip_bgp_dampening_address_mask, NULL, 0); } +static void show_bgp_peerhash_entry(struct hash_backet *backet, void *arg) +{ + struct vty *vty = arg; + struct peer *peer = backet->data; + char buf[SU_ADDRSTRLEN]; + + vty_out(vty, "\tPeer: %s %s\n", peer->host, + sockunion2str(&peer->su, buf, sizeof(buf))); +} + +DEFUN (show_bgp_peerhash, + show_bgp_peerhash_cmd, + "show bgp peerhash", + SHOW_STR + BGP_STR + "Display information about the BGP peerhash\n") +{ + struct list *instances = bm->bgp; + struct listnode *node; + struct bgp *bgp; + + for (ALL_LIST_ELEMENTS_RO(instances, node, bgp)) { + vty_out(vty, "BGP: %s\n", bgp->name); + hash_iterate(bgp->peerhash, show_bgp_peerhash_entry, + vty); + } + + return CMD_SUCCESS; +} + /* also used for encap safi */ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp, afi_t afi, safi_t safi) @@ -11747,6 +11890,7 @@ void bgp_route_init(void) /* show bgp ipv4 flowspec detailed */ install_element(VIEW_NODE, &show_ip_bgp_flowspec_routes_detailed_cmd); + install_element(VIEW_NODE, &show_bgp_peerhash_cmd); } void bgp_route_finish(void) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 476bb3aa05..f0edc8d49a 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -72,11 +72,11 @@ enum bgp_show_adj_route_type { */ #define BGP_MAX_LABELS 2 -/* Ancillary information to struct bgp_info, +/* Ancillary information to struct bgp_path_info, * used for uncommonly used data (aggregation, MPLS, etc.) * and lazily allocated to save memory. */ -struct bgp_info_extra { +struct bgp_path_info_extra { /* Pointer to dampening structure. */ struct bgp_damp_info *damp_info; @@ -150,13 +150,13 @@ struct bgp_info_extra { struct list *bgp_fs_pbr; }; -struct bgp_info { +struct bgp_path_info { /* For linked list. */ - struct bgp_info *next; - struct bgp_info *prev; + struct bgp_path_info *next; + struct bgp_path_info *prev; /* For nexthop linked list */ - LIST_ENTRY(bgp_info) nh_thread; + LIST_ENTRY(bgp_path_info) nh_thread; /* Back pointer to the prefix node */ struct bgp_node *net; @@ -171,11 +171,11 @@ struct bgp_info { struct attr *attr; /* Extra information */ - struct bgp_info_extra *extra; + struct bgp_path_info_extra *extra; /* Multipath information */ - struct bgp_info_mpath *mpath; + struct bgp_path_info_mpath *mpath; /* Uptime. */ time_t uptime; @@ -185,21 +185,21 @@ struct bgp_info { /* BGP information status. */ uint16_t flags; -#define BGP_INFO_IGP_CHANGED (1 << 0) -#define BGP_INFO_DAMPED (1 << 1) -#define BGP_INFO_HISTORY (1 << 2) -#define BGP_INFO_SELECTED (1 << 3) -#define BGP_INFO_VALID (1 << 4) -#define BGP_INFO_ATTR_CHANGED (1 << 5) -#define BGP_INFO_DMED_CHECK (1 << 6) -#define BGP_INFO_DMED_SELECTED (1 << 7) -#define BGP_INFO_STALE (1 << 8) -#define BGP_INFO_REMOVED (1 << 9) -#define BGP_INFO_COUNTED (1 << 10) -#define BGP_INFO_MULTIPATH (1 << 11) -#define BGP_INFO_MULTIPATH_CHG (1 << 12) -#define BGP_INFO_RIB_ATTR_CHG (1 << 13) -#define BGP_INFO_ANNC_NH_SELF (1 << 14) +#define BGP_PATH_IGP_CHANGED (1 << 0) +#define BGP_PATH_DAMPED (1 << 1) +#define BGP_PATH_HISTORY (1 << 2) +#define BGP_PATH_SELECTED (1 << 3) +#define BGP_PATH_VALID (1 << 4) +#define BGP_PATH_ATTR_CHANGED (1 << 5) +#define BGP_PATH_DMED_CHECK (1 << 6) +#define BGP_PATH_DMED_SELECTED (1 << 7) +#define BGP_PATH_STALE (1 << 8) +#define BGP_PATH_REMOVED (1 << 9) +#define BGP_PATH_COUNTED (1 << 10) +#define BGP_PATH_MULTIPATH (1 << 11) +#define BGP_PATH_MULTIPATH_CHG (1 << 12) +#define BGP_PATH_RIB_ATTR_CHG (1 << 13) +#define BGP_PATH_ANNC_NH_SELF (1 << 14) /* BGP route type. This can be static, RIP, OSPF, BGP etc. */ uint8_t type; @@ -224,9 +224,9 @@ struct bgp_info { }; /* Structure used in BGP path selection */ -struct bgp_info_pair { - struct bgp_info *old; - struct bgp_info *new; +struct bgp_path_info_pair { + struct bgp_path_info *old; + struct bgp_path_info *new; }; /* BGP static route configuration. */ @@ -277,20 +277,20 @@ struct bgp_static { #define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \ (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \ && ((attr)->mp_nexthop_len == 16 || (attr)->mp_nexthop_len == 32)) -#define BGP_INFO_COUNTABLE(BI) \ - (!CHECK_FLAG((BI)->flags, BGP_INFO_HISTORY) \ - && !CHECK_FLAG((BI)->flags, BGP_INFO_REMOVED)) +#define BGP_PATH_COUNTABLE(BI) \ + (!CHECK_FLAG((BI)->flags, BGP_PATH_HISTORY) \ + && !CHECK_FLAG((BI)->flags, BGP_PATH_REMOVED)) /* Flags which indicate a route is unuseable in some form */ -#define BGP_INFO_UNUSEABLE \ - (BGP_INFO_HISTORY | BGP_INFO_DAMPED | BGP_INFO_REMOVED) +#define BGP_PATH_UNUSEABLE \ + (BGP_PATH_HISTORY | BGP_PATH_DAMPED | BGP_PATH_REMOVED) /* Macro to check BGP information is alive or not. Sadly, * not equivalent to just checking previous, because of the * sense of the additional VALID flag. */ -#define BGP_INFO_HOLDDOWN(BI) \ - (!CHECK_FLAG((BI)->flags, BGP_INFO_VALID) \ - || CHECK_FLAG((BI)->flags, BGP_INFO_UNUSEABLE)) +#define BGP_PATH_HOLDDOWN(BI) \ + (!CHECK_FLAG((BI)->flags, BGP_PATH_VALID) \ + || CHECK_FLAG((BI)->flags, BGP_PATH_UNUSEABLE)) #define DISTRIBUTE_IN_NAME(F) ((F)->dlist[FILTER_IN].name) #define DISTRIBUTE_IN(F) ((F)->dlist[FILTER_IN].alist) @@ -318,7 +318,11 @@ struct bgp_static { /* path PREFIX (addpath rxid NUMBER) */ #define PATH_ADDPATH_STR_BUFFER PREFIX2STR_BUFFER + 32 -enum bgp_path_type { BGP_PATH_ALL, BGP_PATH_BESTPATH, BGP_PATH_MULTIPATH }; +enum bgp_path_type { + BGP_PATH_SHOW_ALL, + BGP_PATH_SHOW_BESTPATH, + BGP_PATH_SHOW_MULTIPATH +}; static inline void bgp_bump_version(struct bgp_node *node) { @@ -335,7 +339,7 @@ static inline int bgp_fibupd_safi(safi_t safi) } /* Prototypes. */ -extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_info *ri, +extern void bgp_rib_remove(struct bgp_node *rn, struct bgp_path_info *pi, struct peer *peer, afi_t afi, safi_t safi); extern void bgp_process_queue_init(void); extern void bgp_route_init(void); @@ -354,15 +358,19 @@ extern void bgp_clear_stale_route(struct peer *, afi_t, safi_t); extern struct bgp_node *bgp_afi_node_get(struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd); -extern struct bgp_info *bgp_info_lock(struct bgp_info *); -extern struct bgp_info *bgp_info_unlock(struct bgp_info *); -extern void bgp_info_add(struct bgp_node *rn, struct bgp_info *ri); -extern void bgp_info_reap(struct bgp_node *rn, struct bgp_info *ri); -extern void bgp_info_delete(struct bgp_node *rn, struct bgp_info *ri); -extern struct bgp_info_extra *bgp_info_extra_get(struct bgp_info *); -extern void bgp_info_set_flag(struct bgp_node *, struct bgp_info *, uint32_t); -extern void bgp_info_unset_flag(struct bgp_node *, struct bgp_info *, uint32_t); -extern void bgp_info_path_with_addpath_rx_str(struct bgp_info *ri, char *buf); +extern struct bgp_path_info *bgp_path_info_lock(struct bgp_path_info *path); +extern struct bgp_path_info *bgp_path_info_unlock(struct bgp_path_info *path); +extern void bgp_path_info_add(struct bgp_node *rn, struct bgp_path_info *pi); +extern void bgp_path_info_reap(struct bgp_node *rn, struct bgp_path_info *pi); +extern void bgp_path_info_delete(struct bgp_node *rn, struct bgp_path_info *pi); +extern struct bgp_path_info_extra * +bgp_path_info_extra_get(struct bgp_path_info *path); +extern void bgp_path_info_set_flag(struct bgp_node *rn, + struct bgp_path_info *path, uint32_t flag); +extern void bgp_path_info_unset_flag(struct bgp_node *rn, + struct bgp_path_info *path, uint32_t flag); +extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, + char *buf); extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *); @@ -416,38 +424,44 @@ extern void bgp_config_write_network(struct vty *, struct bgp *, afi_t, safi_t); extern void bgp_config_write_distance(struct vty *, struct bgp *, afi_t, safi_t); -extern void bgp_aggregate_increment(struct bgp *, struct prefix *, - struct bgp_info *, afi_t, safi_t); -extern void bgp_aggregate_decrement(struct bgp *, struct prefix *, - struct bgp_info *, afi_t, safi_t); +extern void bgp_aggregate_increment(struct bgp *bgp, struct prefix *p, + struct bgp_path_info *path, afi_t afi, + safi_t safi); +extern void bgp_aggregate_decrement(struct bgp *bgp, struct prefix *p, + struct bgp_path_info *path, afi_t afi, + safi_t safi); -extern uint8_t bgp_distance_apply(struct prefix *, struct bgp_info *, afi_t, - safi_t, struct bgp *); +extern uint8_t bgp_distance_apply(struct prefix *p, struct bgp_path_info *path, + afi_t afi, safi_t safi, struct bgp *bgp); extern afi_t bgp_node_afi(struct vty *); extern safi_t bgp_node_safi(struct vty *); -extern struct bgp_info *info_make(int type, int sub_type, - unsigned short instance, struct peer *peer, - struct attr *attr, struct bgp_node *rn); +extern struct bgp_path_info *info_make(int type, int sub_type, + unsigned short instance, + struct peer *peer, struct attr *attr, + struct bgp_node *rn); -extern void route_vty_out(struct vty *, struct prefix *, struct bgp_info *, int, - safi_t, json_object *); -extern void route_vty_out_tag(struct vty *, struct prefix *, struct bgp_info *, - int, safi_t, json_object *); +extern void route_vty_out(struct vty *vty, struct prefix *p, + struct bgp_path_info *path, int display, safi_t safi, + json_object *json_paths); +extern void route_vty_out_tag(struct vty *vty, struct prefix *p, + struct bgp_path_info *path, int display, + safi_t safi, json_object *json); extern void route_vty_out_tmp(struct vty *vty, struct prefix *p, struct attr *attr, safi_t safi, bool use_json, json_object *json_ar); extern void route_vty_out_overlay(struct vty *vty, struct prefix *p, - struct bgp_info *binfo, int display, + struct bgp_path_info *path, int display, json_object *json); extern int subgroup_process_announce_selected(struct update_subgroup *subgrp, - struct bgp_info *selected, + struct bgp_path_info *selected, struct bgp_node *rn, uint32_t addpath_tx_id); -extern int subgroup_announce_check(struct bgp_node *rn, struct bgp_info *ri, +extern int subgroup_announce_check(struct bgp_node *rn, + struct bgp_path_info *pi, struct update_subgroup *subgrp, struct prefix *p, struct attr *attr); @@ -458,28 +472,30 @@ extern void bgp_process_queues_drain_immediate(void); extern struct bgp_node *bgp_afi_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi, struct prefix *p, struct prefix_rd *prd); -extern struct bgp_info *bgp_info_new(void); -extern void bgp_info_restore(struct bgp_node *, struct bgp_info *); +extern struct bgp_path_info *bgp_path_info_new(void); +extern void bgp_path_info_restore(struct bgp_node *rn, + struct bgp_path_info *path); -extern int bgp_info_cmp_compatible(struct bgp *, struct bgp_info *, - struct bgp_info *, char *pfx_buf, afi_t afi, - safi_t safi); +extern int bgp_path_info_cmp_compatible(struct bgp *bgp, + struct bgp_path_info *new, + struct bgp_path_info *exist, + char *pfx_buf, afi_t afi, safi_t safi); extern void bgp_attr_add_gshut_community(struct attr *attr); extern void bgp_best_selection(struct bgp *bgp, struct bgp_node *rn, struct bgp_maxpaths_cfg *mpath_cfg, - struct bgp_info_pair *result, afi_t afi, + struct bgp_path_info_pair *result, afi_t afi, safi_t safi); extern void bgp_zebra_clear_route_change_flags(struct bgp_node *rn); extern int bgp_zebra_has_route_changed(struct bgp_node *rn, - struct bgp_info *selected); + struct bgp_path_info *selected); extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp, struct bgp_node *rn, struct prefix_rd *prd, afi_t afi, safi_t safi, json_object *json); extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp, - struct prefix *p, struct bgp_info *binfo, + struct prefix *p, struct bgp_path_info *path, afi_t afi, safi_t safi, json_object *json_paths); extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 0a3e4b3c89..60a4e994c9 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -233,7 +233,7 @@ struct bgp_match_peer_compiled { /* 'match peer (A.B.C.D|X:X::X:X|WORD)' */ /* Compares the peer specified in the 'match peer' clause with the peer - received in bgp_info->peer. If it is the same, or if the peer structure + received in bgp_path_info->peer. If it is the same, or if the peer structure received is a peer_group containing it, returns RMAP_MATCH. */ static route_map_result_t route_match_peer(void *rule, const struct prefix *prefix, @@ -251,7 +251,7 @@ static route_map_result_t route_match_peer(void *rule, if (type == RMAP_BGP) { pc = rule; su = &pc->su; - peer = ((struct bgp_info *)object)->peer; + peer = ((struct bgp_path_info *)object)->peer; if (pc->interface) { if (!peer->conf_if) @@ -341,7 +341,7 @@ static route_map_result_t route_match_command(void *rule, u_int32_t locpref = 0; u_int32_t newlocpref = 0; enum lua_rm_status lrm_status; - struct bgp_info *info = (struct bgp_info *)object; + struct bgp_path_info *path = (struct bgp_path_info *)object; lua_State *L = lua_initialize("/etc/frr/lua.scr"); if (L == NULL) @@ -354,18 +354,18 @@ static route_map_result_t route_match_command(void *rule, zlog_debug("Set up prefix table"); /* - * Setup the bgp_info information + * Setup the bgp_path_info information */ lua_newtable(L); - lua_pushinteger(L, info->attr->med); + lua_pushinteger(L, path->attr->med); lua_setfield(L, -2, "metric"); - lua_pushinteger(L, info->attr->nh_ifindex); + lua_pushinteger(L, path->attr->nh_ifindex); lua_setfield(L, -2, "ifindex"); - lua_pushstring(L, info->attr->aspath->str); + lua_pushstring(L, path->attr->aspath->str); lua_setfield(L, -2, "aspath"); - lua_pushinteger(L, info->attr->local_pref); + lua_pushinteger(L, path->attr->local_pref); lua_setfield(L, -2, "localpref"); - zlog_debug("%s %d", info->attr->aspath->str, info->attr->nh_ifindex); + zlog_debug("%s %d", path->attr->aspath->str, path->attr->nh_ifindex); lua_setglobal(L, "nexthop"); zlog_debug("Set up nexthop information"); @@ -383,16 +383,16 @@ static route_map_result_t route_match_command(void *rule, case LUA_RM_MATCH_AND_CHANGE: zlog_debug("MATCH AND CHANGE"); lua_getglobal(L, "nexthop"); - info->attr->med = get_integer(L, "metric"); + path->attr->med = get_integer(L, "metric"); /* * This needs to be abstraced with the set function */ - if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - locpref = info->attr->local_pref; + if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + locpref = path->attr->local_pref; newlocpref = get_integer(L, "localpref"); if (newlocpref != locpref) { - info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); - info->attr->local_pref = newlocpref; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + path->attr->local_pref = newlocpref; } status = RMAP_MATCH; break; @@ -477,13 +477,13 @@ static route_map_result_t route_match_ip_next_hop(void *rule, void *object) { struct access_list *alist; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct prefix_ipv4 p; if (type == RMAP_BGP && prefix->family == AF_INET) { - bgp_info = object; + path = object; p.family = AF_INET; - p.prefix = bgp_info->attr->nexthop; + p.prefix = path->attr->nexthop; p.prefixlen = IPV4_MAX_BITLEN; alist = access_list_lookup(AFI_IP, (char *)rule); @@ -524,13 +524,13 @@ static route_map_result_t route_match_ip_route_source(void *rule, void *object) { struct access_list *alist; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct peer *peer; struct prefix_ipv4 p; if (type == RMAP_BGP && pfx->family == AF_INET) { - bgp_info = object; - peer = bgp_info->peer; + path = object; + peer = path->peer; if (!peer || sockunion_family(&peer->su) != AF_INET) return RMAP_NOMATCH; @@ -610,13 +610,13 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct prefix_list *plist; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct prefix_ipv4 p; if (type == RMAP_BGP && prefix->family == AF_INET) { - bgp_info = object; + path = object; p.family = AF_INET; - p.prefix = bgp_info->attr->nexthop; + p.prefix = path->attr->nexthop; p.prefixlen = IPV4_MAX_BITLEN; plist = prefix_list_lookup(AFI_IP, (char *)rule); @@ -651,19 +651,19 @@ static route_map_result_t route_match_ip_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP && prefix->family == AF_INET) { - bgp_info = (struct bgp_info *)object; - if (!bgp_info || !bgp_info->attr) + path = (struct bgp_path_info *)object; + if (!path || !path->attr) return RMAP_DENYMATCH; /* If nexthop interface's index can't be resolved and nexthop is set to any address then mark it as type `blackhole`. This logic works for matching kernel/static routes like: `ip route add blackhole 10.0.0.1`. */ - if (bgp_info->attr->nexthop.s_addr == INADDR_ANY - && !bgp_info->attr->nh_ifindex) + if (path->attr->nexthop.s_addr == INADDR_ANY + && !path->attr->nh_ifindex) return RMAP_MATCH; } return RMAP_NOMATCH; @@ -692,13 +692,13 @@ route_match_ip_route_source_prefix_list(void *rule, route_map_object_t type, void *object) { struct prefix_list *plist; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct peer *peer; struct prefix_ipv4 p; if (type == RMAP_BGP && prefix->family == AF_INET) { - bgp_info = object; - peer = bgp_info->peer; + path = object; + peer = path->peer; if (!peer || sockunion_family(&peer->su) != AF_INET) return RMAP_NOMATCH; @@ -810,16 +810,16 @@ static route_map_result_t route_match_vni(void *rule, route_map_object_t type, void *object) { vni_t vni = 0; - struct bgp_info *bgp_info = NULL; + struct bgp_path_info *path = NULL; if (type == RMAP_BGP) { vni = *((vni_t *)rule); - bgp_info = (struct bgp_info *)object; + path = (struct bgp_path_info *)object; - if (bgp_info->extra == NULL) + if (path->extra == NULL) return RMAP_NOMATCH; - if (vni == label2vni(&bgp_info->extra->label[0])) + if (vni == label2vni(&path->extra->label[0])) return RMAP_MATCH; } @@ -914,13 +914,13 @@ static route_map_result_t route_match_local_pref(void *rule, void *object) { uint32_t *local_pref; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { local_pref = rule; - bgp_info = object; + path = object; - if (bgp_info->attr->local_pref == *local_pref) + if (path->attr->local_pref == *local_pref) return RMAP_MATCH; else return RMAP_NOMATCH; @@ -974,12 +974,12 @@ static route_map_result_t route_match_metric(void *rule, void *object) { struct rmap_value *rv; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { rv = rule; - bgp_info = object; - return route_value_match(rv, bgp_info->attr->med); + path = object; + return route_value_match(rv, path->attr->med); } return RMAP_NOMATCH; } @@ -999,17 +999,17 @@ static route_map_result_t route_match_aspath(void *rule, { struct as_list *as_list; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { as_list = as_list_lookup((char *)rule); if (as_list == NULL) return RMAP_NOMATCH; - bgp_info = object; + path = object; /* Perform match. */ - return ((as_list_apply(as_list, bgp_info->attr->aspath) + return ((as_list_apply(as_list, path->attr->aspath) == AS_FILTER_DENY) ? RMAP_NOMATCH : RMAP_MATCH); @@ -1047,11 +1047,11 @@ static route_map_result_t route_match_community(void *rule, void *object) { struct community_list *list; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct rmap_community *rcom; if (type == RMAP_BGP) { - bgp_info = object; + path = object; rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, @@ -1060,12 +1060,11 @@ static route_map_result_t route_match_community(void *rule, return RMAP_NOMATCH; if (rcom->exact) { - if (community_list_exact_match( - bgp_info->attr->community, list)) + if (community_list_exact_match(path->attr->community, + list)) return RMAP_MATCH; } else { - if (community_list_match(bgp_info->attr->community, - list)) + if (community_list_match(path->attr->community, list)) return RMAP_MATCH; } } @@ -1115,11 +1114,11 @@ static route_map_result_t route_match_lcommunity(void *rule, void *object) { struct community_list *list; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct rmap_community *rcom; if (type == RMAP_BGP) { - bgp_info = object; + path = object; rcom = rule; list = community_list_lookup(bgp_clist, rcom->name, @@ -1127,7 +1126,7 @@ static route_map_result_t route_match_lcommunity(void *rule, if (!list) return RMAP_NOMATCH; - if (lcommunity_list_match(bgp_info->attr->lcommunity, list)) + if (lcommunity_list_match(path->attr->lcommunity, list)) return RMAP_MATCH; } return RMAP_NOMATCH; @@ -1176,17 +1175,17 @@ static route_map_result_t route_match_ecommunity(void *rule, void *object) { struct community_list *list; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { - bgp_info = object; + path = object; list = community_list_lookup(bgp_clist, (char *)rule, EXTCOMMUNITY_LIST_MASTER); if (!list) return RMAP_NOMATCH; - if (ecommunity_list_match(bgp_info->attr->ecommunity, list)) + if (ecommunity_list_match(path->attr->ecommunity, list)) return RMAP_MATCH; } return RMAP_NOMATCH; @@ -1219,13 +1218,13 @@ static route_map_result_t route_match_origin(void *rule, void *object) { uint8_t *origin; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { origin = rule; - bgp_info = object; + path = object; - if (bgp_info->attr->origin == *origin) + if (path->attr->origin == *origin) return RMAP_MATCH; } @@ -1322,17 +1321,17 @@ static route_map_result_t route_match_interface(void *rule, void *object) { struct interface *ifp; - struct bgp_info *info; + struct bgp_path_info *path; if (type == RMAP_BGP) { - info = object; + path = object; - if (!info || !info->attr) + if (!path || !path->attr) return RMAP_NOMATCH; ifp = if_lookup_by_name_all_vrf((char *)rule); - if (ifp == NULL || ifp->ifindex != info->attr->nh_ifindex) + if (ifp == NULL || ifp->ifindex != path->attr->nh_ifindex) return RMAP_NOMATCH; return RMAP_MATCH; @@ -1368,14 +1367,13 @@ static route_map_result_t route_match_tag(void *rule, route_map_object_t type, void *object) { route_tag_t *tag; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { tag = rule; - bgp_info = object; + path = object; - return ((bgp_info->attr->tag == *tag) ? RMAP_MATCH - : RMAP_NOMATCH); + return ((path->attr->tag == *tag) ? RMAP_MATCH : RMAP_NOMATCH); } return RMAP_NOMATCH; @@ -1402,49 +1400,48 @@ static route_map_result_t route_set_ip_nexthop(void *rule, void *object) { struct rmap_ip_nexthop_set *rins = rule; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct peer *peer; - if (type == RMAP_BGP) { - bgp_info = object; - peer = bgp_info->peer; + if (type != RMAP_BGP) + return RMAP_OKAY; - if (rins->unchanged) { - SET_FLAG(bgp_info->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) { - bgp_info->attr->nexthop.s_addr = - sockunion2ip(peer->su_remote); - bgp_info->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(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_NEXTHOP_PEER_ADDRESS); - bgp_info->attr->nexthop.s_addr = 0; - } - } else { - /* Set next hop value. */ - bgp_info->attr->flag |= - ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); - bgp_info->attr->nexthop = *rins->address; - SET_FLAG(bgp_info->attr->rmap_change_flags, - BATTR_RMAP_IPV4_NHOP_CHANGED); - /* case for MP-BGP : MPLS VPN */ - bgp_info->attr->mp_nexthop_global_in = *rins->address; - bgp_info->attr->mp_nexthop_len = sizeof(*rins->address); + 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); + } 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. */ + 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; @@ -1510,21 +1507,21 @@ static route_map_result_t route_set_local_pref(void *rule, void *object) { struct rmap_value *rv; - struct bgp_info *bgp_info; + struct bgp_path_info *path; uint32_t locpref = 0; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ rv = rule; - bgp_info = object; + path = object; /* Set local preference value. */ - if (bgp_info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - locpref = bgp_info->attr->local_pref; + if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + locpref = path->attr->local_pref; - bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); - bgp_info->attr->local_pref = - route_value_adjust(rv, locpref, bgp_info->peer); + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); + path->attr->local_pref = + route_value_adjust(rv, locpref, path->peer); } return RMAP_OKAY; @@ -1545,16 +1542,15 @@ static route_map_result_t route_set_weight(void *rule, void *object) { struct rmap_value *rv; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ rv = rule; - bgp_info = object; + path = object; /* Set weight value. */ - bgp_info->attr->weight = - route_value_adjust(rv, 0, bgp_info->peer); + path->attr->weight = route_value_adjust(rv, 0, path->peer); } return RMAP_OKAY; @@ -1574,21 +1570,19 @@ static route_map_result_t route_set_metric(void *rule, void *object) { struct rmap_value *rv; - struct bgp_info *bgp_info; + struct bgp_path_info *path; uint32_t med = 0; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ rv = rule; - bgp_info = object; + path = object; - if (bgp_info->attr->flag - & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) - med = bgp_info->attr->med; + if (path->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) + med = path->attr->med; - bgp_info->attr->med = - route_value_adjust(rv, med, bgp_info->peer); - bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); + path->attr->med = route_value_adjust(rv, med, path->peer); + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC); } return RMAP_OKAY; } @@ -1608,15 +1602,15 @@ static route_map_result_t route_set_aspath_prepend(void *rule, { struct aspath *aspath; struct aspath *new; - struct bgp_info *binfo; + struct bgp_path_info *path; if (type == RMAP_BGP) { - binfo = object; + path = object; - if (binfo->attr->aspath->refcnt) - new = aspath_dup(binfo->attr->aspath); + if (path->attr->aspath->refcnt) + new = aspath_dup(path->attr->aspath); else - new = binfo->attr->aspath; + new = path->attr->aspath; if ((uintptr_t)rule > 10) { aspath = rule; @@ -1624,11 +1618,11 @@ static route_map_result_t route_set_aspath_prepend(void *rule, } else { as_t as = aspath_leftmost(new); if (!as) - as = binfo->peer->as; + as = path->peer->as; new = aspath_add_seq_n(new, as, (uintptr_t)rule); } - binfo->attr->aspath = new; + path->attr->aspath = new; } return RMAP_OKAY; @@ -1670,16 +1664,16 @@ static route_map_result_t route_set_aspath_exclude(void *rule, void *object) { struct aspath *new_path, *exclude_path; - struct bgp_info *binfo; + struct bgp_path_info *path; if (type == RMAP_BGP) { exclude_path = rule; - binfo = object; - if (binfo->attr->aspath->refcnt) - new_path = aspath_dup(binfo->attr->aspath); + path = object; + if (path->attr->aspath->refcnt) + new_path = aspath_dup(path->attr->aspath); else - new_path = binfo->attr->aspath; - binfo->attr->aspath = + new_path = path->attr->aspath; + path->attr->aspath = aspath_filter_exclude(new_path, exclude_path); } return RMAP_OKAY; @@ -1705,7 +1699,7 @@ static route_map_result_t route_set_community(void *rule, void *object) { struct rmap_com_set *rcs; - struct bgp_info *binfo; + struct bgp_path_info *path; struct attr *attr; struct community *new = NULL; struct community *old; @@ -1713,8 +1707,8 @@ static route_map_result_t route_set_community(void *rule, if (type == RMAP_BGP) { rcs = rule; - binfo = object; - attr = binfo->attr; + path = object; + attr = path->attr; old = attr->community; /* "none" case. */ @@ -1723,7 +1717,7 @@ static route_map_result_t route_set_community(void *rule, attr->community = NULL; /* See the longer comment down below. */ if (old && old->refcnt == 0) - community_free(old); + community_free(&old); return RMAP_OKAY; } @@ -1732,7 +1726,7 @@ static route_map_result_t route_set_community(void *rule, merge = community_merge(community_dup(old), rcs->com); new = community_uniq_sort(merge); - community_free(merge); + community_free(&merge); } else new = community_dup(rcs->com); @@ -1742,7 +1736,7 @@ static route_map_result_t route_set_community(void *rule, * Really need to cleanup attribute caching sometime. */ if (old && old->refcnt == 0) - community_free(old); + community_free(&old); /* will be interned by caller if required */ attr->community = new; @@ -1796,7 +1790,7 @@ static void route_set_community_free(void *rule) struct rmap_com_set *rcs = rule; if (rcs->com) - community_free(rcs->com); + community_free(&rcs->com); XFREE(MTYPE_ROUTE_MAP_COMPILED, rcs); } @@ -1821,7 +1815,7 @@ static route_map_result_t route_set_lcommunity(void *rule, void *object) { struct rmap_lcom_set *rcs; - struct bgp_info *binfo; + struct bgp_path_info *path; struct attr *attr; struct lcommunity *new = NULL; struct lcommunity *old; @@ -1829,8 +1823,8 @@ static route_map_result_t route_set_lcommunity(void *rule, if (type == RMAP_BGP) { rcs = rule; - binfo = object; - attr = binfo->attr; + path = object; + attr = path->attr; old = attr->lcommunity; /* "none" case. */ @@ -1937,16 +1931,16 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, struct lcommunity *merge; struct lcommunity *new; struct lcommunity *old; - struct bgp_info *binfo; + struct bgp_path_info *path; if (type == RMAP_BGP) { if (!rule) return RMAP_OKAY; - binfo = object; + path = object; list = community_list_lookup(bgp_clist, rule, LARGE_COMMUNITY_LIST_MASTER); - old = binfo->attr->lcommunity; + old = path->attr->lcommunity; if (list && old) { merge = lcommunity_list_match_delete( @@ -1963,13 +1957,13 @@ static route_map_result_t route_set_lcommunity_delete(void *rule, lcommunity_free(&old); if (new->size == 0) { - binfo->attr->lcommunity = NULL; - binfo->attr->flag &= ~ATTR_FLAG_BIT( + path->attr->lcommunity = NULL; + path->attr->flag &= ~ATTR_FLAG_BIT( BGP_ATTR_LARGE_COMMUNITIES); lcommunity_free(&new); } else { - binfo->attr->lcommunity = new; - binfo->attr->flag |= ATTR_FLAG_BIT( + path->attr->lcommunity = new; + path->attr->flag |= ATTR_FLAG_BIT( BGP_ATTR_LARGE_COMMUNITIES); } } @@ -2022,22 +2016,22 @@ static route_map_result_t route_set_community_delete( struct community *merge; struct community *new; struct community *old; - struct bgp_info *binfo; + struct bgp_path_info *path; if (type == RMAP_BGP) { if (!rule) return RMAP_OKAY; - binfo = object; + path = object; list = community_list_lookup(bgp_clist, rule, COMMUNITY_LIST_MASTER); - old = binfo->attr->community; + old = path->attr->community; if (list && old) { merge = community_list_match_delete(community_dup(old), list); new = community_uniq_sort(merge); - community_free(merge); + community_free(&merge); /* HACK: if the old community is not intern'd, * we should free it here, or all reference to it may be @@ -2045,16 +2039,16 @@ static route_map_result_t route_set_community_delete( * Really need to cleanup attribute caching sometime. */ if (old->refcnt == 0) - community_free(old); + community_free(&old); if (new->size == 0) { - binfo->attr->community = NULL; - binfo->attr->flag &= + path->attr->community = NULL; + path->attr->flag &= ~ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); - community_free(new); + community_free(&new); } else { - binfo->attr->community = new; - binfo->attr->flag |= + path->attr->community = new; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES); } } @@ -2104,17 +2098,17 @@ static route_map_result_t route_set_ecommunity(void *rule, struct ecommunity *ecom; struct ecommunity *new_ecom; struct ecommunity *old_ecom; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { ecom = rule; - bgp_info = object; + path = object; if (!ecom) return RMAP_OKAY; /* We assume additive for Extended Community. */ - old_ecom = bgp_info->attr->ecommunity; + old_ecom = path->attr->ecommunity; if (old_ecom) { new_ecom = ecommunity_merge(ecommunity_dup(old_ecom), @@ -2130,9 +2124,9 @@ static route_map_result_t route_set_ecommunity(void *rule, new_ecom = ecommunity_dup(ecom); /* will be intern()'d or attr_flush()'d by bgp_update_main() */ - bgp_info->attr->ecommunity = new_ecom; + path->attr->ecommunity = new_ecom; - bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES); } return RMAP_OKAY; } @@ -2190,13 +2184,13 @@ static route_map_result_t route_set_origin(void *rule, void *object) { uint8_t *origin; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { origin = rule; - bgp_info = object; + path = object; - bgp_info->attr->origin = *origin; + path->attr->origin = *origin; } return RMAP_OKAY; @@ -2239,12 +2233,11 @@ static route_map_result_t route_set_atomic_aggregate(void *rule, route_map_object_t type, void *object) { - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { - bgp_info = object; - bgp_info->attr->flag |= - ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); + path = object; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE); } return RMAP_OKAY; @@ -2279,16 +2272,16 @@ static route_map_result_t route_set_aggregator_as(void *rule, route_map_object_t type, void *object) { - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct aggregator *aggregator; if (type == RMAP_BGP) { - bgp_info = object; + path = object; aggregator = rule; - bgp_info->attr->aggregator_as = aggregator->as; - bgp_info->attr->aggregator_addr = aggregator->address; - bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); + path->attr->aggregator_as = aggregator->as; + path->attr->aggregator_addr = aggregator->address; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AGGREGATOR); } return RMAP_OKAY; @@ -2327,20 +2320,20 @@ struct route_map_rule_cmd route_set_aggregator_as_cmd = { route_set_aggregator_as_compile, route_set_aggregator_as_free, }; -/* Set tag to object. object must be pointer to struct bgp_info */ +/* Set tag to object. object must be pointer to struct bgp_path_info */ static route_map_result_t route_set_tag(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { route_tag_t *tag; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { tag = rule; - bgp_info = object; + path = object; /* Set tag value */ - bgp_info->attr->tag = *tag; + path->attr->tag = *tag; } return RMAP_OKAY; @@ -2352,27 +2345,26 @@ static struct route_map_rule_cmd route_set_tag_cmd = { route_map_rule_tag_free, }; -/* Set label-index to object. object must be pointer to struct bgp_info */ +/* Set label-index to object. object must be pointer to struct bgp_path_info */ static route_map_result_t route_set_label_index(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { struct rmap_value *rv; - struct bgp_info *bgp_info; + struct bgp_path_info *path; uint32_t label_index; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ rv = rule; - bgp_info = object; + path = object; /* Set label-index value. */ label_index = rv->value; if (label_index) { - bgp_info->attr->label_index = label_index; - bgp_info->attr->flag |= - ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); + path->attr->label_index = label_index; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID); } } @@ -2429,17 +2421,17 @@ static route_map_result_t route_match_ipv6_next_hop(void *rule, void *object) { struct in6_addr *addr = rule; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { - bgp_info = object; + path = object; - if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr)) + if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr)) return RMAP_MATCH; - if (bgp_info->attr->mp_nexthop_len + if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL - && IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_local, rule)) + && IPV6_ADDR_SAME(&path->attr->mp_nexthop_local, rule)) return RMAP_MATCH; return RMAP_NOMATCH; @@ -2514,16 +2506,16 @@ static route_map_result_t route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct in6_addr *addr = rule; if (type == RMAP_BGP && prefix->family == AF_INET6) { - bgp_info = (struct bgp_info *)object; - if (!bgp_info || !bgp_info->attr) + path = (struct bgp_path_info *)object; + if (!path || !path->attr) return RMAP_DENYMATCH; - if (IPV6_ADDR_SAME(&bgp_info->attr->mp_nexthop_global, addr) - && !bgp_info->attr->nh_ifindex) + if (IPV6_ADDR_SAME(&path->attr->mp_nexthop_global, addr) + && !path->attr->nh_ifindex) return RMAP_MATCH; } return RMAP_NOMATCH; @@ -2564,22 +2556,21 @@ static route_map_result_t route_set_ipv6_nexthop_global(void *rule, void *object) { struct in6_addr *address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ address = rule; - bgp_info = object; + path = object; /* Set next hop value. */ - bgp_info->attr->mp_nexthop_global = *address; + path->attr->mp_nexthop_global = *address; /* Set nexthop length. */ - if (bgp_info->attr->mp_nexthop_len == 0) - bgp_info->attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL; + if (path->attr->mp_nexthop_len == 0) + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - SET_FLAG(bgp_info->attr->rmap_change_flags, + SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_IPV6_GLOBAL_NHOP_CHANGED); } @@ -2622,25 +2613,25 @@ static route_map_result_t route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct peer *peer; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ - bgp_info = object; - peer = bgp_info->peer; + path = object; + peer = path->peer; 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_INET6) { /* Set next hop preference to global */ - bgp_info->attr->mp_nexthop_prefer_global = TRUE; - SET_FLAG(bgp_info->attr->rmap_change_flags, + path->attr->mp_nexthop_prefer_global = TRUE; + SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); } else { - bgp_info->attr->mp_nexthop_prefer_global = FALSE; - SET_FLAG(bgp_info->attr->rmap_change_flags, + path->attr->mp_nexthop_prefer_global = FALSE; + SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED); } } @@ -2678,23 +2669,23 @@ static route_map_result_t route_set_ipv6_nexthop_local(void *rule, void *object) { struct in6_addr *address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ address = rule; - bgp_info = object; + path = object; /* Set next hop value. */ - bgp_info->attr->mp_nexthop_local = *address; + path->attr->mp_nexthop_local = *address; /* Set nexthop length. */ - if (bgp_info->attr->mp_nexthop_len + if (path->attr->mp_nexthop_len != BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - bgp_info->attr->mp_nexthop_len = + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - SET_FLAG(bgp_info->attr->rmap_change_flags, + SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_IPV6_LL_NHOP_CHANGED); } @@ -2741,13 +2732,13 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, void *object) { struct in6_addr peer_address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; struct peer *peer; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ - bgp_info = object; - peer = bgp_info->peer; + path = object; + peer = path->peer; if ((CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN) || CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) @@ -2756,14 +2747,13 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, peer_address = peer->su_remote->sin6.sin6_addr; /* Set next hop value and length in attribute. */ if (IN6_IS_ADDR_LINKLOCAL(&peer_address)) { - bgp_info->attr->mp_nexthop_local = peer_address; - if (bgp_info->attr->mp_nexthop_len != 32) - bgp_info->attr->mp_nexthop_len = 32; + path->attr->mp_nexthop_local = peer_address; + if (path->attr->mp_nexthop_len != 32) + path->attr->mp_nexthop_len = 32; } else { - bgp_info->attr->mp_nexthop_global = - peer_address; - if (bgp_info->attr->mp_nexthop_len == 0) - bgp_info->attr->mp_nexthop_len = 16; + path->attr->mp_nexthop_global = peer_address; + if (path->attr->mp_nexthop_len == 0) + path->attr->mp_nexthop_len = 16; } } else if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_OUT)) { @@ -2776,12 +2766,12 @@ static route_map_result_t route_set_ipv6_nexthop_peer(void *rule, * nexthops, whether we send one or both is determined * elsewhere. */ - SET_FLAG(bgp_info->attr->rmap_change_flags, + SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_NEXTHOP_PEER_ADDRESS); /* clear next hop value. */ - memset(&(bgp_info->attr->mp_nexthop_global), 0, + memset(&(path->attr->mp_nexthop_global), 0, sizeof(struct in6_addr)); - memset(&(bgp_info->attr->mp_nexthop_local), 0, + memset(&(path->attr->mp_nexthop_local), 0, sizeof(struct in6_addr)); } } @@ -2820,16 +2810,16 @@ static route_map_result_t route_set_vpnv4_nexthop(void *rule, void *object) { struct in_addr *address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ address = rule; - bgp_info = object; + path = object; /* Set next hop value. */ - bgp_info->attr->mp_nexthop_global_in = *address; - bgp_info->attr->mp_nexthop_len = 4; + path->attr->mp_nexthop_global_in = *address; + path->attr->mp_nexthop_len = 4; } return RMAP_OKAY; @@ -2860,17 +2850,17 @@ static route_map_result_t route_set_vpnv6_nexthop(void *rule, void *object) { struct in6_addr *address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { /* Fetch routemap's rule information. */ address = rule; - bgp_info = object; + path = object; /* Set next hop value. */ - memcpy(&bgp_info->attr->mp_nexthop_global, address, + memcpy(&path->attr->mp_nexthop_global, address, sizeof(struct in6_addr)); - bgp_info->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; + path->attr->mp_nexthop_len = BGP_ATTR_NHLEN_VPNV6_GLOBAL; } return RMAP_OKAY; @@ -2916,14 +2906,14 @@ static route_map_result_t route_set_originator_id(void *rule, void *object) { struct in_addr *address; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { address = rule; - bgp_info = object; + path = object; - bgp_info->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); - bgp_info->attr->originator_id = *address; + path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID); + path->attr->originator_id = *address; } return RMAP_OKAY; @@ -4181,7 +4171,7 @@ DEFUN (set_community, ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index), "community", str); - community_free(com); + community_free(&com); return ret; } diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c index 56566525a4..77bd2eaefa 100644 --- a/bgpd/bgp_rpki.c +++ b/bgpd/bgp_rpki.c @@ -217,12 +217,12 @@ static route_map_result_t route_match(void *rule, const struct prefix *prefix, route_map_object_t type, void *object) { int *rpki_status = rule; - struct bgp_info *bgp_info; + struct bgp_path_info *path; if (type == RMAP_BGP) { - bgp_info = object; + path = object; - if (rpki_validate_prefix(bgp_info->peer, bgp_info->attr, prefix) + if (rpki_validate_prefix(path->peer, path->attr, prefix) == *rpki_status) { return RMAP_MATCH; } @@ -418,13 +418,13 @@ static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi, for (ain = bgp_node->adj_in; ain; ain = ain->next) { int ret; - struct bgp_info *bgp_info = bgp_node->info; + struct bgp_path_info *path = bgp_node->info; mpls_label_t *label = NULL; uint32_t num_labels = 0; - if (bgp_info && bgp_info->extra) { - label = bgp_info->extra->label; - num_labels = bgp_info->extra->num_labels; + if (path && path->extra) { + label = path->extra->label; + num_labels = path->extra->num_labels; } ret = bgp_update(ain->peer, &bgp_node->p, ain->addpath_rx_id, ain->attr, afi, safi, ZEBRA_ROUTE_BGP, diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c index 0700e0ac24..d539fad510 100644 --- a/bgpd/bgp_snmp.c +++ b/bgpd/bgp_snmp.c @@ -674,14 +674,15 @@ static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[], return NULL; } -static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[], - size_t *length, struct bgp *bgp, - struct prefix_ipv4 *addr, int exact) +static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[], + size_t *length, struct bgp *bgp, + struct prefix_ipv4 *addr, + int exact) { oid *offset; int offsetlen; - struct bgp_info *binfo; - struct bgp_info *min; + struct bgp_path_info *path; + struct bgp_path_info *min; struct bgp_node *rn; union sockunion su; unsigned int len; @@ -714,9 +715,9 @@ static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[], if (rn) { bgp_unlock_node(rn); - for (binfo = rn->info; binfo; binfo = binfo->next) - if (sockunion_same(&binfo->peer->su, &su)) - return binfo; + for (path = rn->info; path; path = path->next) + if (sockunion_same(&path->peer->su, &su)) + return path; } } else { offset = name + v->namelen; @@ -761,22 +762,22 @@ static struct bgp_info *bgp4PathAttrLookup(struct variable *v, oid name[], do { min = NULL; - for (binfo = rn->info; binfo; binfo = binfo->next) { - if (binfo->peer->su.sin.sin_family == AF_INET + for (path = rn->info; path; path = path->next) { + if (path->peer->su.sin.sin_family == AF_INET && ntohl(paddr.s_addr) - < ntohl(binfo->peer->su.sin + < ntohl(path->peer->su.sin .sin_addr .s_addr)) { if (min) { - if (ntohl(binfo->peer->su.sin + if (ntohl(path->peer->su.sin .sin_addr .s_addr) < ntohl(min->peer->su.sin .sin_addr .s_addr)) - min = binfo; + min = path; } else - min = binfo; + min = path; } } @@ -812,7 +813,7 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], WriteMethod **write_method) { struct bgp *bgp; - struct bgp_info *binfo; + struct bgp_path_info *path; struct prefix_ipv4 addr; bgp = bgp_get_default(); @@ -824,13 +825,13 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], return NULL; memset(&addr, 0, sizeof(struct prefix_ipv4)); - binfo = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact); - if (!binfo) + path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact); + if (!path) return NULL; switch (v->magic) { case BGP4PATHATTRPEER: /* 1 */ - return SNMP_IPADDRESS(binfo->peer->su.sin.sin_addr); + return SNMP_IPADDRESS(path->peer->su.sin.sin_addr); break; case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */ return SNMP_INTEGER(addr.prefixlen); @@ -839,28 +840,28 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], return SNMP_IPADDRESS(addr.prefix); break; case BGP4PATHATTRORIGIN: /* 4 */ - return SNMP_INTEGER(binfo->attr->origin); + return SNMP_INTEGER(path->attr->origin); break; case BGP4PATHATTRASPATHSEGMENT: /* 5 */ - return aspath_snmp_pathseg(binfo->attr->aspath, var_len); + return aspath_snmp_pathseg(path->attr->aspath, var_len); break; case BGP4PATHATTRNEXTHOP: /* 6 */ - return SNMP_IPADDRESS(binfo->attr->nexthop); + return SNMP_IPADDRESS(path->attr->nexthop); break; case BGP4PATHATTRMULTIEXITDISC: /* 7 */ - return SNMP_INTEGER(binfo->attr->med); + return SNMP_INTEGER(path->attr->med); break; case BGP4PATHATTRLOCALPREF: /* 8 */ - return SNMP_INTEGER(binfo->attr->local_pref); + return SNMP_INTEGER(path->attr->local_pref); break; case BGP4PATHATTRATOMICAGGREGATE: /* 9 */ return SNMP_INTEGER(1); break; case BGP4PATHATTRAGGREGATORAS: /* 10 */ - return SNMP_INTEGER(binfo->attr->aggregator_as); + return SNMP_INTEGER(path->attr->aggregator_as); break; case BGP4PATHATTRAGGREGATORADDR: /* 11 */ - return SNMP_IPADDRESS(binfo->attr->aggregator_addr); + return SNMP_IPADDRESS(path->attr->aggregator_addr); break; case BGP4PATHATTRCALCLOCALPREF: /* 12 */ return SNMP_INTEGER(-1); @@ -868,7 +869,7 @@ static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[], case BGP4PATHATTRBEST: /* 13 */ #define BGP4_PathAttrBest_false 1 #define BGP4_PathAttrBest_true 2 - if (CHECK_FLAG(binfo->flags, BGP_INFO_SELECTED)) + if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED)) return SNMP_INTEGER(BGP4_PathAttrBest_true); else return SNMP_INTEGER(BGP4_PathAttrBest_false); diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c index f7bb6e1054..231f326cef 100644 --- a/bgpd/bgp_table.c +++ b/bgpd/bgp_table.c @@ -104,7 +104,7 @@ struct bgp_table *bgp_table_init(struct bgp *bgp, afi_t afi, safi_t safi) route_table_set_info(rt->route_table, rt); /* - * pointer to bgp instance allows working back from bgp_info to bgp + * pointer to bgp instance allows working back from bgp_path_info to bgp */ rt->bgp = bgp; diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 2a4c3690c9..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) @@ -1906,7 +1906,7 @@ int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi) * configured addpath-tx knob */ int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi, - struct bgp_info *ri) + struct bgp_path_info *pi) { if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_ALL_PATHS)) @@ -1914,7 +1914,7 @@ int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi, if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_ADDPATH_TX_BESTPATH_PER_AS) - && CHECK_FLAG(ri->flags, BGP_INFO_DMED_SELECTED)) + && CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED)) return 1; return 0; diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h index c1cbca6dcf..b1d852d384 100644 --- a/bgpd/bgp_updgrp.h +++ b/bgpd/bgp_updgrp.h @@ -293,7 +293,7 @@ typedef int (*updgrp_walkcb)(struct update_group *updgrp, void *ctx); struct updwalk_context { struct vty *vty; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; uint64_t updgrp_id; uint64_t subgrp_id; bgp_policy_type_e policy_type; @@ -442,7 +442,7 @@ extern void subgroup_announce_all(struct update_subgroup *subgrp); extern void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw); extern void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_node *rn, struct bgp_info *ri); + struct bgp_node *rn, struct bgp_path_info *pi); extern void subgroup_clear_table(struct update_subgroup *subgrp); extern void update_group_announce(struct bgp *bgp); extern void update_group_announce_rrclients(struct bgp *bgp); @@ -455,7 +455,8 @@ extern void bgp_adj_out_remove_subgroup(struct bgp_node *rn, struct update_subgroup *subgrp); extern void bgp_adj_out_set_subgroup(struct bgp_node *rn, struct update_subgroup *subgrp, - struct attr *attr, struct bgp_info *binfo); + struct attr *attr, + struct bgp_path_info *path); extern void bgp_adj_out_unset_subgroup(struct bgp_node *rn, struct update_subgroup *subgrp, char withdraw, uint32_t addpath_tx_id); @@ -469,7 +470,7 @@ extern int update_group_clear_update_dbg(struct update_group *updgrp, extern void update_bgp_group_free(struct bgp *bgp); extern int bgp_addpath_encode_tx(struct peer *peer, afi_t afi, safi_t safi); extern int bgp_addpath_tx_path(struct peer *peer, afi_t afi, safi_t safi, - struct bgp_info *ri); + struct bgp_path_info *pi); /* * Inline functions diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c index 6ffb1d448b..81b782c2b0 100644 --- a/bgpd/bgp_updgrp_adv.c +++ b/bgpd/bgp_updgrp_adv.c @@ -101,7 +101,7 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) { struct updwalk_context *ctx = arg; struct update_subgroup *subgrp; - struct bgp_info *ri; + struct bgp_path_info *pi; afi_t afi; safi_t safi; struct peer *peer; @@ -140,15 +140,15 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) adj_next = adj->next; if (adj->subgroup == subgrp) { - for (ri = ctx->rn->info; ri; - ri = ri->next) { - if (ri->addpath_tx_id + for (pi = ctx->rn->info; pi; + pi = pi->next) { + if (pi->addpath_tx_id == adj->addpath_tx_id) { break; } } - if (!ri) { + if (!pi) { subgroup_process_announce_selected( subgrp, NULL, ctx->rn, @@ -157,32 +157,32 @@ static int group_announce_route_walkcb(struct update_group *updgrp, void *arg) } } - for (ri = ctx->rn->info; ri; ri = ri->next) { + for (pi = ctx->rn->info; pi; pi = pi->next) { /* Skip the bestpath for now */ - if (ri == ctx->ri) + if (pi == ctx->pi) continue; subgroup_process_announce_selected( - subgrp, ri, ctx->rn, - ri->addpath_tx_id); + subgrp, pi, ctx->rn, + pi->addpath_tx_id); } /* Process the bestpath last so the "show [ip] * bgp neighbor x.x.x.x advertised" * output shows the attributes from the bestpath */ - if (ctx->ri) + if (ctx->pi) subgroup_process_announce_selected( - subgrp, ctx->ri, ctx->rn, - ctx->ri->addpath_tx_id); + subgrp, ctx->pi, ctx->rn, + ctx->pi->addpath_tx_id); } /* An update-group that does not use addpath */ else { - if (ctx->ri) { + if (ctx->pi) { subgroup_process_announce_selected( - subgrp, ctx->ri, ctx->rn, - ctx->ri->addpath_tx_id); + subgrp, ctx->pi, ctx->rn, + ctx->pi->addpath_tx_id); } else { /* Find the addpath_tx_id of the path we * had advertised and @@ -429,7 +429,7 @@ bgp_advertise_clean_subgroup(struct update_subgroup *subgrp, void bgp_adj_out_set_subgroup(struct bgp_node *rn, struct update_subgroup *subgrp, struct attr *attr, - struct bgp_info *binfo) + struct bgp_path_info *path) { struct bgp_adj_out *adj = NULL; struct bgp_advertise *adv; @@ -438,10 +438,10 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn, return; /* Look for adjacency information. */ - adj = adj_lookup(rn, subgrp, binfo->addpath_tx_id); + adj = adj_lookup(rn, subgrp, path->addpath_tx_id); if (!adj) { - adj = bgp_adj_out_alloc(subgrp, rn, binfo->addpath_tx_id); + adj = bgp_adj_out_alloc(subgrp, rn, path->addpath_tx_id); if (!adj) return; } @@ -452,8 +452,9 @@ void bgp_adj_out_set_subgroup(struct bgp_node *rn, adv = adj->adv; adv->rn = rn; - assert(adv->binfo == NULL); - adv->binfo = bgp_info_lock(binfo); /* bgp_info adj_out reference */ + assert(adv->pathi == NULL); + /* bgp_path_info adj_out reference */ + adv->pathi = bgp_path_info_lock(path); if (attr) adv->baa = bgp_advertise_intern(subgrp->hash, attr); @@ -568,7 +569,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp, struct bgp_table *table) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *ri; struct attr attr; struct peer *peer; afi_t afi; @@ -594,7 +595,7 @@ void subgroup_announce_table(struct update_subgroup *subgrp, for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) + if (CHECK_FLAG(ri->flags, BGP_PATH_SELECTED) || (addpath_capable && bgp_addpath_tx_path(peer, afi, safi, ri))) { if (subgroup_announce_check(rn, ri, subgrp, @@ -663,11 +664,12 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) { struct bgp *bgp; struct attr attr; - struct bgp_info *info, init_info, tmp_info; + struct aspath *aspath; + struct bgp_path_info tmp_info; struct prefix p; struct peer *from; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *ri; struct peer *peer; int ret = RMAP_DENYMATCH; afi_t afi; @@ -687,59 +689,46 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) from = bgp->peer_self; bgp_attr_default_set(&attr, BGP_ORIGIN_IGP); + aspath = attr.aspath; + attr.local_pref = bgp->default_local_pref; - if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) { - /* IPv6 global nexthop must be included. - */ - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; - - /* If the peer is on shared nextwork and - * we have link-local nexthop set it. */ - if (peer->shared_network - && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) - attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } - init_info.attr = &attr; - info = &init_info; - bgp_attr_intern(info->attr); - memset(&p, 0, sizeof(p)); p.family = afi2family(afi); p.prefixlen = 0; + if ((afi == AFI_IP6) || peer_cap_enhe(peer, afi, safi)) { + /* IPv6 global nexthop must be included. */ + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL; + + /* If the peer is on shared nextwork and we have link-local + nexthop set it. */ + if (peer->shared_network + && !IN6_IS_ADDR_UNSPECIFIED(&peer->nexthop.v6_local)) + attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; + } + if (peer->default_rmap[afi][safi].name) { SET_FLAG(bgp->peer_self->rmap_type, PEER_RMAP_TYPE_DEFAULT); for (rn = bgp_table_top(bgp->rib[afi][safi]); rn; rn = bgp_route_next(rn)) { for (ri = rn->info; ri; ri = ri->next) { + struct attr dummy_attr; + + /* Provide dummy so the route-map can't modify + * the attributes */ + bgp_attr_dup(&dummy_attr, ri->attr); tmp_info.peer = ri->peer; - tmp_info.attr = ri->attr; - - /* Reset attributes every time to avoid \ - * unexpected as-path prepends */ - bgp_attr_default_set(tmp_info.attr, - BGP_ORIGIN_IGP); - - if ((afi == AFI_IP6) - || peer_cap_enhe(peer, afi, safi)) { - tmp_info.attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL; - - if (peer->shared_network - && !IN6_IS_ADDR_UNSPECIFIED( - &peer->nexthop.v6_local)) - tmp_info.attr->mp_nexthop_len = - BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL; - } + tmp_info.attr = &dummy_attr; ret = route_map_apply( peer->default_rmap[afi][safi].map, &rn->p, RMAP_BGP, &tmp_info); - info = &tmp_info; - bgp_attr_intern(info->attr); - + /* The route map might have set attributes. If + * we don't flush them + * here, they will be leaked. */ + bgp_attr_flush(&dummy_attr); if (ret != RMAP_DENYMATCH) break; } @@ -761,13 +750,12 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) SUBGRP_STATUS_DEFAULT_ORIGINATE)) { if (bgp_flag_check(bgp, BGP_FLAG_GRACEFUL_SHUTDOWN)) { - bgp_attr_add_gshut_community(info->attr); + bgp_attr_add_gshut_community(&attr); } SET_FLAG(subgrp->sflags, SUBGRP_STATUS_DEFAULT_ORIGINATE); - subgroup_default_update_packet(subgrp, info->attr, - from); + subgroup_default_update_packet(subgrp, &attr, from); /* The 'neighbor x.x.x.x default-originate' default will * act as an @@ -787,7 +775,8 @@ void subgroup_default_originate(struct update_subgroup *subgrp, int withdraw) BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); } } - aspath_unintern(&info->attr->aspath); + + aspath_unintern(&aspath); } /* @@ -830,10 +819,10 @@ void subgroup_announce_all(struct update_subgroup *subgrp) * input route. */ void group_announce_route(struct bgp *bgp, afi_t afi, safi_t safi, - struct bgp_node *rn, struct bgp_info *ri) + struct bgp_node *rn, struct bgp_path_info *pi) { struct updwalk_context ctx; - ctx.ri = ri; + ctx.pi = pi; ctx.rn = rn; update_group_af_walk(bgp, afi, safi, group_announce_route_walkcb, &ctx); } diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 56a82c801c..c4fcea948f 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -687,7 +687,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) struct bgp_adj_out *adj; struct bgp_advertise *adv; struct bgp_node *rn = NULL; - struct bgp_info *binfo = NULL; + struct bgp_path_info *path = NULL; bgp_size_t total_attr_len = 0; unsigned long attrlen_pos = 0; size_t mpattrlen_pos = 0; @@ -731,7 +731,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) rn = adv->rn; adj = adv->adj; addpath_tx_id = adj->addpath_tx_id; - binfo = adv->binfo; + path = adv->pathi; space_remaining = STREAM_CONCAT_REMAIN(s, snlri, STREAM_SIZE(s)) - BGP_MAX_PACKET_SIZE_OVERFLOW; @@ -747,8 +747,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) if (stream_empty(s)) { struct peer *from = NULL; - if (binfo) - from = binfo->peer; + if (path) + from = path->peer; /* 1: Write the BGP message header - 16 bytes marker, 2 * bytes length, @@ -821,13 +821,13 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) prd = (struct prefix_rd *)&rn->prn->p; if (safi == SAFI_LABELED_UNICAST) { - label = bgp_adv_label(rn, binfo, peer, afi, + label = bgp_adv_label(rn, path, peer, afi, safi); label_pnt = &label; num_labels = 1; - } else if (binfo && binfo->extra) { - label_pnt = &binfo->extra->label[0]; - num_labels = binfo->extra->num_labels; + } else if (path && path->extra) { + label_pnt = &path->extra->label[0]; + num_labels = path->extra->num_labels; } if (stream_empty(snlri)) @@ -1123,6 +1123,8 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp, snprintf(tx_id_buf, sizeof(tx_id_buf), " with addpath ID %u", BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE); + else + tx_id_buf[0] = '\0'; zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s%s %s", (SUBGRP_UPDGRP(subgrp))->id, subgrp->id, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 40c79e1da2..cdabe35fde 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2301,7 +2301,7 @@ DEFUN (bgp_default_show_hostname, "bgp default show-hostname", "BGP specific commands\n" "Configure BGP defaults\n" - "Show hostname in certain command ouputs\n") + "Show hostname in certain command outputs\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); bgp_flag_set(bgp, BGP_FLAG_SHOW_HOSTNAME); @@ -2314,7 +2314,7 @@ DEFUN (no_bgp_default_show_hostname, NO_STR "BGP specific commands\n" "Configure BGP defaults\n" - "Show hostname in certain command ouputs\n") + "Show hostname in certain command outputs\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); bgp_flag_unset(bgp, BGP_FLAG_SHOW_HOSTNAME); @@ -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; @@ -2835,7 +2836,7 @@ static int peer_conf_interface_get(struct vty *vty, const char *conf_if, peer = peer_lookup_by_conf_if(bgp, conf_if); if (peer) { if (as_str) - ret = peer_remote_as(bgp, &su, conf_if, &as, as_type, + ret = peer_remote_as(bgp, NULL, conf_if, &as, as_type, afi, safi); } else { if (bgp_flag_check(bgp, BGP_FLAG_NO_DEFAULT_IPV4) @@ -4767,14 +4768,17 @@ static int peer_default_originate_set_vty(struct vty *vty, const char *peer_str, { int ret; struct peer *peer; + struct route_map *route_map; peer = peer_and_group_lookup_vty(vty, peer_str); if (!peer) return CMD_WARNING_CONFIG_FAILED; - if (set) - ret = peer_default_originate_set(peer, afi, safi, rmap); - else + if (set) { + route_map = route_map_lookup_warn_noexist(vty, rmap); + ret = peer_default_originate_set(peer, afi, safi, + rmap, route_map); + } else ret = peer_default_originate_unset(peer, afi, safi); return bgp_vty_return(vty, ret); @@ -5593,6 +5597,7 @@ static int peer_route_map_set_vty(struct vty *vty, const char *ip_str, int ret; struct peer *peer; int direct = RMAP_IN; + struct route_map *route_map; peer = peer_and_group_lookup_vty(vty, ip_str); if (!peer) @@ -5604,7 +5609,8 @@ static int peer_route_map_set_vty(struct vty *vty, const char *ip_str, else if (strncmp(direct_str, "o", 1) == 0) direct = RMAP_OUT; - ret = peer_route_map_set(peer, afi, safi, direct, name_str); + route_map = route_map_lookup_warn_noexist(vty, name_str); + ret = peer_route_map_set(peer, afi, safi, direct, name_str, route_map); return bgp_vty_return(vty, ret); } @@ -5691,12 +5697,14 @@ static int peer_unsuppress_map_set_vty(struct vty *vty, const char *ip_str, { int ret; struct peer *peer; + struct route_map *route_map; peer = peer_and_group_lookup_vty(vty, ip_str); if (!peer) return CMD_WARNING_CONFIG_FAILED; - ret = peer_unsuppress_map_set(peer, afi, safi, name_str); + route_map = route_map_lookup_warn_noexist(vty, name_str); + ret = peer_unsuppress_map_set(peer, afi, safi, name_str, route_map); return bgp_vty_return(vty, ret); } @@ -6008,7 +6016,7 @@ DEFUN (neighbor_allowas_in, NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Accept as-path with my AS present in it\n" - "Number of occurances of AS number\n" + "Number of occurences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { int idx_peer = 1; @@ -6042,7 +6050,7 @@ ALIAS_HIDDEN( "neighbor allowas-in [<(1-10)|origin>]", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Accept as-path with my AS present in it\n" - "Number of occurances of AS number\n" + "Number of occurences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (no_neighbor_allowas_in, @@ -6052,7 +6060,7 @@ DEFUN (no_neighbor_allowas_in, NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "allow local ASN appears in aspath attribute\n" - "Number of occurances of AS number\n" + "Number of occurences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") { int idx_peer = 2; @@ -6074,7 +6082,7 @@ ALIAS_HIDDEN( "no neighbor allowas-in [<(1-10)|origin>]", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "allow local ASN appears in aspath attribute\n" - "Number of occurances of AS number\n" + "Number of occurences of AS number\n" "Only accept my AS in the as-path if the route was originated in my AS\n") DEFUN (neighbor_ttl_security, @@ -6646,7 +6654,7 @@ DEFPY (af_route_map_vpn_imexport, bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP( MTYPE_ROUTE_MAP_NAME, rmap_str); bgp->vpn_policy[afi].rmap[dir] = - route_map_lookup_by_name(rmap_str); + route_map_lookup_warn_noexist(vty, rmap_str); if (!bgp->vpn_policy[afi].rmap[dir]) return CMD_SUCCESS; } else { @@ -6719,7 +6727,7 @@ DEFPY(af_import_vrf_route_map, af_import_vrf_route_map_cmd, bgp->vpn_policy[afi].rmap_name[dir] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_str); bgp->vpn_policy[afi].rmap[dir] = - route_map_lookup_by_name(rmap_str); + route_map_lookup_warn_noexist(vty, rmap_str); if (!bgp->vpn_policy[afi].rmap[dir]) return CMD_SUCCESS; } else { @@ -6742,13 +6750,12 @@ ALIAS(af_import_vrf_route_map, af_no_import_vrf_route_map_cmd, "Vrf routes being filtered\n" "Specify route map\n") -DEFPY (bgp_imexport_vrf, - bgp_imexport_vrf_cmd, - "[no] import vrf NAME$import_name", - NO_STR - "Import routes from another VRF\n" - "VRF to import from\n" - "The name of the VRF\n") +DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd, + "[no] import vrf VIEWVRFNAME$import_name", + NO_STR + "Import routes from another VRF\n" + "VRF to import from\n" + "The name of the VRF\n") { VTY_DECLVAR_CONTEXT(bgp, bgp); struct listnode *node; @@ -7524,12 +7531,13 @@ DEFUN (show_bgp_memory, count = mtype_stats_alloc(MTYPE_BGP_ROUTE); vty_out(vty, "%ld BGP routes, using %s of memory\n", count, mtype_memstr(memstrbuf, sizeof(memstrbuf), - count * sizeof(struct bgp_info))); + count * sizeof(struct bgp_path_info))); if ((count = mtype_stats_alloc(MTYPE_BGP_ROUTE_EXTRA))) vty_out(vty, "%ld BGP route ancillaries, using %s of memory\n", count, - mtype_memstr(memstrbuf, sizeof(memstrbuf), - count * sizeof(struct bgp_info_extra))); + mtype_memstr( + memstrbuf, sizeof(memstrbuf), + count * sizeof(struct bgp_path_info_extra))); if ((count = mtype_stats_alloc(MTYPE_BGP_STATIC))) vty_out(vty, "%ld Static routes, using %s of memory\n", count, @@ -9608,7 +9616,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_string_add( json_nxt, print_store, - "recieved"); + "received"); } } json_object_object_add( @@ -10216,7 +10224,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json, json_object_object_add( json_neigh, "gracefulRestartInfo", json_grace); } else { - vty_out(vty, " Graceful restart informations:\n"); + vty_out(vty, " Graceful restart information:\n"); if (p->status == Established) { vty_out(vty, " End-of-RIB send: "); FOREACH_AFI_SAFI (afi, safi) { @@ -11376,6 +11384,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", @@ -11659,6 +11684,8 @@ DEFUN (bgp_redistribute_ipv4_rmap, int type; struct bgp_redist *red; bool changed; + struct route_map *route_map = route_map_lookup_warn_noexist( + vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11667,7 +11694,8 @@ DEFUN (bgp_redistribute_ipv4_rmap, } red = bgp_redist_add(bgp, AFI_IP, type, 0); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } @@ -11731,6 +11759,8 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric, uint32_t metric; struct bgp_redist *red; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11740,7 +11770,8 @@ DEFUN (bgp_redistribute_ipv4_rmap_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, type, 0); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } @@ -11774,6 +11805,8 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap, uint32_t metric; struct bgp_redist *red; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP, argv[idx_protocol]->text); if (type < 0) { @@ -11784,7 +11817,8 @@ DEFUN (bgp_redistribute_ipv4_metric_rmap, red = bgp_redist_add(bgp, AFI_IP, type, 0); changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, type, metric); - changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP, type, 0, changed); } @@ -11849,6 +11883,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap, unsigned short instance; int protocol; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11857,7 +11893,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap, instance = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } @@ -11937,6 +11974,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, unsigned short instance; int protocol; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -11947,7 +11986,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_rmap_metric, metric = strtoul(argv[idx_number_2]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP, protocol, instance); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); @@ -11988,6 +12028,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, unsigned short instance; int protocol; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); if (strncmp(argv[idx_ospf_table]->arg, "o", 1) == 0) protocol = ZEBRA_ROUTE_OSPF; @@ -12000,7 +12042,8 @@ DEFUN (bgp_redistribute_ipv4_ospf_metric_rmap, red = bgp_redist_add(bgp, AFI_IP, protocol, instance); changed = bgp_redistribute_metric_set(bgp, red, AFI_IP, protocol, metric); - changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP, protocol, instance, changed); } @@ -12126,6 +12169,8 @@ DEFUN (bgp_redistribute_ipv6_rmap, int type; struct bgp_redist *red; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -12134,7 +12179,8 @@ DEFUN (bgp_redistribute_ipv6_rmap, } red = bgp_redist_add(bgp, AFI_IP6, type, 0); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } @@ -12184,6 +12230,8 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric, uint32_t metric; struct bgp_redist *red; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -12193,7 +12241,8 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric, metric = strtoul(argv[idx_number]->arg, NULL, 10); red = bgp_redist_add(bgp, AFI_IP6, type, 0); - changed = bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed = + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6, type, metric); return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); @@ -12217,6 +12266,8 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap, uint32_t metric; struct bgp_redist *red; bool changed; + struct route_map *route_map = + route_map_lookup_warn_noexist(vty, argv[idx_word]->arg); type = proto_redistnum(AFI_IP6, argv[idx_protocol]->text); if (type < 0) { @@ -12228,7 +12279,8 @@ DEFUN (bgp_redistribute_ipv6_metric_rmap, red = bgp_redist_add(bgp, AFI_IP6, type, 0); changed = bgp_redistribute_metric_set(bgp, red, AFI_IP6, SAFI_UNICAST, metric); - changed |= bgp_redistribute_rmap_set(red, argv[idx_word]->arg); + changed |= + bgp_redistribute_rmap_set(red, argv[idx_word]->arg, route_map); return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed); } @@ -13126,6 +13178,8 @@ void bgp_vty_init(void) install_element(BGP_VPNV4_NODE, &no_neighbor_route_server_client_cmd); install_element(BGP_VPNV6_NODE, &neighbor_route_server_client_cmd); install_element(BGP_VPNV6_NODE, &no_neighbor_route_server_client_cmd); + install_element(BGP_EVPN_NODE, &neighbor_route_server_client_cmd); + install_element(BGP_EVPN_NODE, &no_neighbor_route_server_client_cmd); install_element(BGP_FLOWSPECV4_NODE, &neighbor_route_server_client_cmd); install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_route_server_client_cmd); @@ -13578,6 +13632,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); @@ -13743,11 +13798,11 @@ static void community_list_perror(struct vty *vty, int ret) /* "community-list" keyword help string. */ #define COMMUNITY_LIST_STR "Add a community list entry\n" -/* ip community-list standard */ -DEFUN (ip_community_list_standard, - ip_community_list_standard_cmd, - "ip community-list <(1-99)|standard WORD> AA:NN...", - IP_STR +/*community-list standard */ +DEFUN (community_list_standard, + bgp_community_list_standard_cmd, + "bgp community-list <(1-99)|standard WORD> AA:NN...", + BGP_STR COMMUNITY_LIST_STR "Community list number (standard)\n" "Add an standard community-list entry\n" @@ -13761,6 +13816,14 @@ DEFUN (ip_community_list_standard, int style = COMMUNITY_LIST_STANDARD; int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'bgp community-list <(1-99)|(100-500)|standard|expanded> AA:NN'\n"); + zlog_warn("Deprecated option: 'ip community-list <(1-99)|(100-500)|standard|expanded> AA:NN' being used"); + } + argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; @@ -13783,7 +13846,68 @@ DEFUN (ip_community_list_standard, return CMD_SUCCESS; } -DEFUN (no_ip_community_list_standard_all, +#if CONFDATE > 20191005 +CPP_NOTICE("bgpd: remove deprecated 'ip community-list <(1-99)|(100-500)|standard|expanded> AA:NN' command") +#endif +ALIAS (community_list_standard, + ip_community_list_standard_cmd, + "ip community-list <(1-99)|standard WORD> AA:NN...", + IP_STR + COMMUNITY_LIST_STR + "Community list number (standard)\n" + "Add an standard community-list entry\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + COMMUNITY_VAL_STR) + +DEFUN (no_community_list_standard_all, + no_bgp_community_list_standard_all_cmd, + "no bgp community-list <(1-99)|standard WORD> AA:NN...", + NO_STR + BGP_STR + COMMUNITY_LIST_STR + "Community list number (standard)\n" + "Add an standard community-list entry\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + COMMUNITY_VAL_STR) +{ + char *cl_name_or_number = NULL; + int direct = 0; + int style = COMMUNITY_LIST_STANDARD; + + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'no bgp community-list <(1-99)|(100-500)|standard|expanded> AA:NN'\n"); + zlog_warn("Deprecated option: 'no ip community-list <(1-99)|(100-500)|standard|expanded> |AA:NN' being used"); + } + + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_name_or_number = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); + + int ret = community_list_unset(bgp_clist, cl_name_or_number, str, + direct, style); + + XFREE(MTYPE_TMP, str); + + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; +} +ALIAS (no_community_list_standard_all, no_ip_community_list_standard_all_cmd, "no ip community-list <(1-99)|standard WORD> AA:NN...", NO_STR @@ -13795,38 +13919,12 @@ DEFUN (no_ip_community_list_standard_all, "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) -{ - char *cl_name_or_number = NULL; - int direct = 0; - int style = COMMUNITY_LIST_STANDARD; - int idx = 0; - argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); - cl_name_or_number = argv[idx]->arg; - direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT - : COMMUNITY_DENY; - argv_find(argv, argc, "AA:NN", &idx); - char *str = argv_concat(argv, argc, idx); - - int ret = community_list_unset(bgp_clist, cl_name_or_number, str, - direct, style); - - XFREE(MTYPE_TMP, str); - - if (ret < 0) { - community_list_perror(vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; -} - -/* ip community-list expanded */ -DEFUN (ip_community_list_expanded_all, - ip_community_list_expanded_all_cmd, - "ip community-list <(100-500)|expanded WORD> AA:NN...", - IP_STR +/*community-list expanded */ +DEFUN (community_list_expanded_all, + bgp_community_list_expanded_all_cmd, + "bgp community-list <(100-500)|expanded WORD> AA:NN...", + BGP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" "Add an expanded community-list entry\n" @@ -13840,6 +13938,12 @@ DEFUN (ip_community_list_expanded_all, int style = COMMUNITY_LIST_EXPANDED; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'bgp community-list <(1-99)|(100-500)|standard|expanded> AA:NN'\n"); + zlog_warn("Deprecated option: 'ip community-list <(1-99)|(100-500)|standard|expanded> AA:NN' being used"); + } argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; @@ -13862,10 +13966,9 @@ DEFUN (ip_community_list_expanded_all, return CMD_SUCCESS; } -DEFUN (no_ip_community_list_expanded_all, - no_ip_community_list_expanded_all_cmd, - "no ip community-list <(100-500)|expanded WORD> AA:NN...", - NO_STR +ALIAS (community_list_expanded_all, + ip_community_list_expanded_all_cmd, + "ip community-list <(100-500)|expanded WORD> AA:NN...", IP_STR COMMUNITY_LIST_STR "Community list number (expanded)\n" @@ -13874,12 +13977,31 @@ DEFUN (no_ip_community_list_expanded_all, "Specify community to reject\n" "Specify community to accept\n" COMMUNITY_VAL_STR) + +DEFUN (no_community_list_expanded_all, + no_bgp_community_list_expanded_all_cmd, + "no bgp community-list <(100-500)|expanded WORD> AA:NN...", + NO_STR + BGP_STR + COMMUNITY_LIST_STR + "Community list number (expanded)\n" + "Add an expanded community-list entry\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + COMMUNITY_VAL_STR) { char *cl_name_or_number = NULL; int direct = 0; int style = COMMUNITY_LIST_EXPANDED; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'no community-list <(1-99)|(100-500)|standard|expanded> AA:NN'\n"); + zlog_warn("Deprecated option: 'no community-list <(1-99)|(100-500)|standard|expanded> AA:NN' being used"); + } argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_name_or_number = argv[idx]->arg; @@ -13901,6 +14023,19 @@ DEFUN (no_ip_community_list_expanded_all, return CMD_SUCCESS; } +ALIAS (no_community_list_expanded_all, + no_ip_community_list_expanded_all_cmd, + "no ip community-list <(100-500)|expanded WORD> AA:NN...", + NO_STR + IP_STR + COMMUNITY_LIST_STR + "Community list number (expanded)\n" + "Add an expanded community-list entry\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + COMMUNITY_VAL_STR) + /* Return configuration string of community-list entry. */ static const char *community_list_config_str(struct community_entry *entry) { @@ -13948,16 +14083,23 @@ static void community_list_show(struct vty *vty, struct community_list *list) } } -DEFUN (show_ip_community_list, - show_ip_community_list_cmd, - "show ip community-list", +DEFUN (show_community_list, + show_bgp_community_list_cmd, + "show bgp community-list", SHOW_STR - IP_STR + BGP_STR "List community-list\n") { struct community_list *list; struct community_list_master *cm; + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used"); + } cm = community_list_master_lookup(bgp_clist, COMMUNITY_LIST_MASTER); if (!cm) return CMD_SUCCESS; @@ -13971,11 +14113,18 @@ DEFUN (show_ip_community_list, return CMD_SUCCESS; } -DEFUN (show_ip_community_list_arg, - show_ip_community_list_arg_cmd, - "show ip community-list <(1-500)|WORD>", +ALIAS (show_community_list, + show_ip_community_list_cmd, + "show ip community-list", SHOW_STR IP_STR + "List community-list\n") + +DEFUN (show_community_list_arg, + show_bgp_community_list_arg_cmd, + "show bgp community-list <(1-500)|WORD>", + SHOW_STR + BGP_STR "List community-list\n" "Community-list number\n" "Community-list name\n") @@ -13983,6 +14132,13 @@ DEFUN (show_ip_community_list_arg, int idx_comm_list = 3; struct community_list *list; + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp community-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show community-list <(1-500)|WORD>' being used"); + } list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, COMMUNITY_LIST_MASTER); if (!list) { @@ -13995,6 +14151,15 @@ DEFUN (show_ip_community_list_arg, return CMD_SUCCESS; } +ALIAS (show_community_list_arg, + show_ip_community_list_arg_cmd, + "show ip community-list <(1-500)|WORD>", + SHOW_STR + IP_STR + "List community-list\n" + "Community-list number\n" + "Community-list name\n") + /* * Large Community code. */ @@ -14008,6 +14173,12 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc, int idx = 0; char *cl_name; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'bgp large-community-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: 'large-community-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT : COMMUNITY_DENY; @@ -14053,6 +14224,12 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, char *str = NULL; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'no bgp large-community-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: 'no ip large-community-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } argv_find(argv, argc, "permit", &idx); argv_find(argv, argc, "deny", &idx); @@ -14096,10 +14273,13 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc, #define LCOMMUNITY_LIST_STR "Add a large community list entry\n" #define LCOMMUNITY_VAL_STR "large community in 'aa:bb:cc' format\n" -DEFUN (ip_lcommunity_list_standard, - ip_lcommunity_list_standard_cmd, - "ip large-community-list (1-99) ", - IP_STR +#if CONFDATE > 20191005 +CPP_NOTICE("bgpd: remove deprecated 'ip large-community-list <(1-99)|(100-500)|standard|expanded> ' command") +#endif +DEFUN (lcommunity_list_standard, + bgp_lcommunity_list_standard_cmd, + "bgp large-community-list (1-99) ", + BGP_STR LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" "Specify large community to reject\n" @@ -14109,13 +14289,22 @@ DEFUN (ip_lcommunity_list_standard, LARGE_COMMUNITY_LIST_STANDARD, 0); } -DEFUN (ip_lcommunity_list_standard1, - ip_lcommunity_list_standard1_cmd, - "ip large-community-list (1-99) AA:BB:CC...", +ALIAS (lcommunity_list_standard, + ip_lcommunity_list_standard_cmd, + "ip large-community-list (1-99) ", IP_STR LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" "Specify large community to reject\n" + "Specify large community to accept\n") + +DEFUN (lcommunity_list_standard1, + bgp_lcommunity_list_standard1_cmd, + "bgp large-community-list (1-99) AA:BB:CC...", + BGP_STR + LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { @@ -14123,11 +14312,21 @@ DEFUN (ip_lcommunity_list_standard1, LARGE_COMMUNITY_LIST_STANDARD, 0); } -DEFUN (ip_lcommunity_list_expanded, - ip_lcommunity_list_expanded_cmd, - "ip large-community-list (100-500) LINE...", +ALIAS (lcommunity_list_standard1, + ip_lcommunity_list_standard1_cmd, + "ip large-community-list (1-99) AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) + +DEFUN (lcommunity_list_expanded, + bgp_lcommunity_list_expanded_cmd, + "bgp large-community-list (100-500) LINE...", + BGP_STR + LCOMMUNITY_LIST_STR "Large Community list number (expanded)\n" "Specify large community to reject\n" "Specify large community to accept\n" @@ -14137,11 +14336,21 @@ DEFUN (ip_lcommunity_list_expanded, LARGE_COMMUNITY_LIST_EXPANDED, 0); } -DEFUN (ip_lcommunity_list_name_standard, - ip_lcommunity_list_name_standard_cmd, - "ip large-community-list standard WORD ", +ALIAS (lcommunity_list_expanded, + ip_lcommunity_list_expanded_cmd, + "ip large-community-list (100-500) LINE...", IP_STR LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") + +DEFUN (lcommunity_list_name_standard, + bgp_lcommunity_list_name_standard_cmd, + "bgp large-community-list standard WORD ", + BGP_STR + LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" "Large Community list name\n" "Specify large community to reject\n" @@ -14151,14 +14360,24 @@ DEFUN (ip_lcommunity_list_name_standard, LARGE_COMMUNITY_LIST_STANDARD, 1); } -DEFUN (ip_lcommunity_list_name_standard1, - ip_lcommunity_list_name_standard1_cmd, - "ip large-community-list standard WORD AA:BB:CC...", +ALIAS (lcommunity_list_name_standard, + ip_lcommunity_list_name_standard_cmd, + "ip large-community-list standard WORD ", IP_STR LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" "Large Community list name\n" "Specify large community to reject\n" + "Specify large community to accept\n") + +DEFUN (lcommunity_list_name_standard1, + bgp_lcommunity_list_name_standard1_cmd, + "bgp large-community-list standard WORD AA:BB:CC...", + BGP_STR + LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" "Specify large community to accept\n" LCOMMUNITY_VAL_STR) { @@ -14166,11 +14385,22 @@ DEFUN (ip_lcommunity_list_name_standard1, LARGE_COMMUNITY_LIST_STANDARD, 1); } -DEFUN (ip_lcommunity_list_name_expanded, - ip_lcommunity_list_name_expanded_cmd, - "ip large-community-list expanded WORD LINE...", +ALIAS (lcommunity_list_name_standard1, + ip_lcommunity_list_name_standard1_cmd, + "ip large-community-list standard WORD AA:BB:CC...", IP_STR LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) + +DEFUN (lcommunity_list_name_expanded, + bgp_lcommunity_list_name_expanded_cmd, + "bgp large-community-list expanded WORD LINE...", + BGP_STR + LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" "Large Community list name\n" "Specify large community to reject\n" @@ -14181,12 +14411,23 @@ DEFUN (ip_lcommunity_list_name_expanded, LARGE_COMMUNITY_LIST_EXPANDED, 1); } -DEFUN (no_ip_lcommunity_list_standard_all, - no_ip_lcommunity_list_standard_all_cmd, - "no ip large-community-list <(1-99)|(100-500)|WORD>", - NO_STR +ALIAS (lcommunity_list_name_expanded, + ip_lcommunity_list_name_expanded_cmd, + "ip large-community-list expanded WORD LINE...", IP_STR LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") + +DEFUN (no_lcommunity_list_standard_all, + no_bgp_lcommunity_list_standard_all_cmd, + "no bgp large-community-list <(1-99)|(100-500)|WORD>", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" "Large Community list number (expanded)\n" "Large Community list name\n") @@ -14195,12 +14436,22 @@ DEFUN (no_ip_lcommunity_list_standard_all, LARGE_COMMUNITY_LIST_STANDARD); } -DEFUN (no_ip_lcommunity_list_name_expanded_all, - no_ip_lcommunity_list_name_expanded_all_cmd, - "no ip large-community-list expanded WORD", +ALIAS (no_lcommunity_list_standard_all, + no_ip_lcommunity_list_standard_all_cmd, + "no ip large-community-list <(1-99)|(100-500)|WORD>", NO_STR IP_STR LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Large Community list number (expanded)\n" + "Large Community list name\n") + +DEFUN (no_lcommunity_list_name_expanded_all, + no_bgp_lcommunity_list_name_expanded_all_cmd, + "no bgp large-community-list expanded WORD", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" "Large Community list name\n") { @@ -14208,12 +14459,21 @@ DEFUN (no_ip_lcommunity_list_name_expanded_all, LARGE_COMMUNITY_LIST_EXPANDED); } -DEFUN (no_ip_lcommunity_list_standard, - no_ip_lcommunity_list_standard_cmd, - "no ip large-community-list (1-99) AA:AA:NN...", +ALIAS (no_lcommunity_list_name_expanded_all, + no_ip_lcommunity_list_name_expanded_all_cmd, + "no ip large-community-list expanded WORD", NO_STR IP_STR LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large Community list name\n") + +DEFUN (no_lcommunity_list_standard, + no_bgp_lcommunity_list_standard_cmd, + "no bgp large-community-list (1-99) AA:AA:NN...", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Large Community list number (standard)\n" "Specify large community to reject\n" "Specify large community to accept\n" @@ -14223,12 +14483,23 @@ DEFUN (no_ip_lcommunity_list_standard, LARGE_COMMUNITY_LIST_STANDARD); } -DEFUN (no_ip_lcommunity_list_expanded, - no_ip_lcommunity_list_expanded_cmd, - "no ip large-community-list (100-500) LINE...", +ALIAS (no_lcommunity_list_standard, + no_ip_lcommunity_list_standard_cmd, + "no ip large-community-list (1-99) AA:AA:NN...", NO_STR IP_STR LCOMMUNITY_LIST_STR + "Large Community list number (standard)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) + +DEFUN (no_lcommunity_list_expanded, + no_bgp_lcommunity_list_expanded_cmd, + "no bgp large-community-list (100-500) LINE...", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Large Community list number (expanded)\n" "Specify large community to reject\n" "Specify large community to accept\n" @@ -14238,12 +14509,23 @@ DEFUN (no_ip_lcommunity_list_expanded, LARGE_COMMUNITY_LIST_EXPANDED); } -DEFUN (no_ip_lcommunity_list_name_standard, - no_ip_lcommunity_list_name_standard_cmd, - "no ip large-community-list standard WORD AA:AA:NN...", +ALIAS (no_lcommunity_list_expanded, + no_ip_lcommunity_list_expanded_cmd, + "no ip large-community-list (100-500) LINE...", NO_STR IP_STR LCOMMUNITY_LIST_STR + "Large Community list number (expanded)\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") + +DEFUN (no_lcommunity_list_name_standard, + no_bgp_lcommunity_list_name_standard_cmd, + "no bgp large-community-list standard WORD AA:AA:NN...", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Specify standard large-community-list\n" "Large Community list name\n" "Specify large community to reject\n" @@ -14254,12 +14536,24 @@ DEFUN (no_ip_lcommunity_list_name_standard, LARGE_COMMUNITY_LIST_STANDARD); } -DEFUN (no_ip_lcommunity_list_name_expanded, - no_ip_lcommunity_list_name_expanded_cmd, - "no ip large-community-list expanded WORD LINE...", +ALIAS (no_lcommunity_list_name_standard, + no_ip_lcommunity_list_name_standard_cmd, + "no ip large-community-list standard WORD AA:AA:NN...", NO_STR IP_STR LCOMMUNITY_LIST_STR + "Specify standard large-community-list\n" + "Large Community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + LCOMMUNITY_VAL_STR) + +DEFUN (no_lcommunity_list_name_expanded, + no_bgp_lcommunity_list_name_expanded_cmd, + "no bgp large-community-list expanded WORD LINE...", + NO_STR + BGP_STR + LCOMMUNITY_LIST_STR "Specify expanded large-community-list\n" "Large community list name\n" "Specify large community to reject\n" @@ -14270,6 +14564,18 @@ DEFUN (no_ip_lcommunity_list_name_expanded, LARGE_COMMUNITY_LIST_EXPANDED); } +ALIAS (no_lcommunity_list_name_expanded, + no_ip_lcommunity_list_name_expanded_cmd, + "no ip large-community-list expanded WORD LINE...", + NO_STR + IP_STR + LCOMMUNITY_LIST_STR + "Specify expanded large-community-list\n" + "Large community list name\n" + "Specify large community to reject\n" + "Specify large community to accept\n" + "An ordered list as a regular-expression\n") + static void lcommunity_list_show(struct vty *vty, struct community_list *list) { struct community_entry *entry; @@ -14300,15 +14606,23 @@ static void lcommunity_list_show(struct vty *vty, struct community_list *list) } } -DEFUN (show_ip_lcommunity_list, - show_ip_lcommunity_list_cmd, - "show ip large-community-list", +DEFUN (show_lcommunity_list, + show_bgp_lcommunity_list_cmd, + "show bgp large-community-list", SHOW_STR - IP_STR + BGP_STR "List large-community list\n") { struct community_list *list; struct community_list_master *cm; + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used"); + } cm = community_list_master_lookup(bgp_clist, LARGE_COMMUNITY_LIST_MASTER); @@ -14324,16 +14638,31 @@ DEFUN (show_ip_lcommunity_list, return CMD_SUCCESS; } -DEFUN (show_ip_lcommunity_list_arg, - show_ip_lcommunity_list_arg_cmd, - "show ip large-community-list <(1-500)|WORD>", +ALIAS (show_lcommunity_list, + show_ip_lcommunity_list_cmd, + "show ip large-community-list", SHOW_STR IP_STR + "List large-community list\n") + +DEFUN (show_lcommunity_list_arg, + show_bgp_lcommunity_list_arg_cmd, + "show bgp large-community-list <(1-500)|WORD>", + SHOW_STR + BGP_STR "List large-community list\n" "large-community-list number\n" "large-community-list name\n") { struct community_list *list; + int idx = 0; + + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp large-community-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show large-community-list <(1-500)|WORD>' being used"); + } list = community_list_lookup(bgp_clist, argv[3]->arg, LARGE_COMMUNITY_LIST_MASTER); @@ -14347,14 +14676,23 @@ DEFUN (show_ip_lcommunity_list_arg, return CMD_SUCCESS; } +ALIAS (show_lcommunity_list_arg, + show_ip_lcommunity_list_arg_cmd, + "show ip large-community-list <(1-500)|WORD>", + SHOW_STR + IP_STR + "List large-community list\n" + "large-community-list number\n" + "large-community-list name\n") + /* "extcommunity-list" keyword help string. */ #define EXTCOMMUNITY_LIST_STR "Add a extended community list entry\n" #define EXTCOMMUNITY_VAL_STR "Extended community attribute in 'rt aa:nn_or_IPaddr:nn' OR 'soo aa:nn_or_IPaddr:nn' format\n" -DEFUN (ip_extcommunity_list_standard, - ip_extcommunity_list_standard_cmd, - "ip extcommunity-list <(1-99)|standard WORD> AA:NN...", - IP_STR +DEFUN (extcommunity_list_standard, + bgp_extcommunity_list_standard_cmd, + "bgp extcommunity-list <(1-99)|standard WORD> AA:NN...", + BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (standard)\n" "Specify standard extcommunity-list\n" @@ -14368,6 +14706,12 @@ DEFUN (ip_extcommunity_list_standard, char *cl_number_or_name = NULL; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: 'ip extcommunity-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } argv_find(argv, argc, "(1-99)", &idx); argv_find(argv, argc, "WORD", &idx); cl_number_or_name = argv[idx]->arg; @@ -14389,11 +14733,26 @@ DEFUN (ip_extcommunity_list_standard, return CMD_SUCCESS; } -DEFUN (ip_extcommunity_list_name_expanded, - ip_extcommunity_list_name_expanded_cmd, - "ip extcommunity-list <(100-500)|expanded WORD> LINE...", +#if CONFDATE > 20191005 +CPP_NOTICE("bgpd: remove deprecated 'ip extcommunity-list <(1-99)|(100-500)|standard|expanded> ' command") +#endif +ALIAS (extcommunity_list_standard, + ip_extcommunity_list_standard_cmd, + "ip extcommunity-list <(1-99)|standard WORD> AA:NN...", IP_STR EXTCOMMUNITY_LIST_STR + "Extended Community list number (standard)\n" + "Specify standard extcommunity-list\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + EXTCOMMUNITY_VAL_STR) + +DEFUN (extcommunity_list_name_expanded, + bgp_extcommunity_list_name_expanded_cmd, + "bgp extcommunity-list <(100-500)|expanded WORD> LINE...", + BGP_STR + EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" "Extended Community list name\n" @@ -14406,6 +14765,13 @@ DEFUN (ip_extcommunity_list_name_expanded, char *cl_number_or_name = NULL; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'extcommunity-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: ‘ip extcommunity-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } + argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_number_or_name = argv[idx]->arg; @@ -14427,7 +14793,64 @@ DEFUN (ip_extcommunity_list_name_expanded, return CMD_SUCCESS; } -DEFUN (no_ip_extcommunity_list_standard_all, +ALIAS (extcommunity_list_name_expanded, + ip_extcommunity_list_name_expanded_cmd, + "ip extcommunity-list <(100-500)|expanded WORD> LINE...", + IP_STR + EXTCOMMUNITY_LIST_STR + "Extended Community list number (expanded)\n" + "Specify expanded extcommunity-list\n" + "Extended Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + "An ordered list as a regular-expression\n") + +DEFUN (no_extcommunity_list_standard_all, + no_bgp_extcommunity_list_standard_all_cmd, + "no bgp extcommunity-list <(1-99)|standard WORD> AA:NN...", + NO_STR + BGP_STR + EXTCOMMUNITY_LIST_STR + "Extended Community list number (standard)\n" + "Specify standard extcommunity-list\n" + "Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + EXTCOMMUNITY_VAL_STR) +{ + int style = EXTCOMMUNITY_LIST_STANDARD; + int direct = 0; + char *cl_number_or_name = NULL; + + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'no bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: ‘no ip extcommunity-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } + argv_find(argv, argc, "(1-99)", &idx); + argv_find(argv, argc, "WORD", &idx); + cl_number_or_name = argv[idx]->arg; + direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT + : COMMUNITY_DENY; + argv_find(argv, argc, "AA:NN", &idx); + char *str = argv_concat(argv, argc, idx); + + int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, + direct, style); + + XFREE(MTYPE_TMP, str); + + if (ret < 0) { + community_list_perror(vty, ret); + return CMD_WARNING_CONFIG_FAILED; + } + + return CMD_SUCCESS; +} + +ALIAS (no_extcommunity_list_standard_all, no_ip_extcommunity_list_standard_all_cmd, "no ip extcommunity-list <(1-99)|standard WORD> AA:NN...", NO_STR @@ -14439,38 +14862,12 @@ DEFUN (no_ip_extcommunity_list_standard_all, "Specify community to reject\n" "Specify community to accept\n" EXTCOMMUNITY_VAL_STR) -{ - int style = EXTCOMMUNITY_LIST_STANDARD; - int direct = 0; - char *cl_number_or_name = NULL; - int idx = 0; - argv_find(argv, argc, "(1-99)", &idx); - argv_find(argv, argc, "WORD", &idx); - cl_number_or_name = argv[idx]->arg; - direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT - : COMMUNITY_DENY; - argv_find(argv, argc, "AA:NN", &idx); - char *str = argv_concat(argv, argc, idx); - - int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str, - direct, style); - - XFREE(MTYPE_TMP, str); - - if (ret < 0) { - community_list_perror(vty, ret); - return CMD_WARNING_CONFIG_FAILED; - } - - return CMD_SUCCESS; -} - -DEFUN (no_ip_extcommunity_list_expanded_all, - no_ip_extcommunity_list_expanded_all_cmd, - "no ip extcommunity-list <(100-500)|expanded WORD> LINE...", +DEFUN (no_extcommunity_list_expanded_all, + no_bgp_extcommunity_list_expanded_all_cmd, + "no bgp extcommunity-list <(100-500)|expanded WORD> LINE...", NO_STR - IP_STR + BGP_STR EXTCOMMUNITY_LIST_STR "Extended Community list number (expanded)\n" "Specify expanded extcommunity-list\n" @@ -14484,6 +14881,12 @@ DEFUN (no_ip_extcommunity_list_expanded_all, char *cl_number_or_name = NULL; int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'no bgp extcommunity-list <(1-99)|(100-500)|standard|expanded> '\n"); + zlog_warn("Deprecated option: ‘no ip extcommunity-list <(1-99)|(100-500)|standard|expanded> ' being used"); + } argv_find(argv, argc, "(100-500)", &idx); argv_find(argv, argc, "WORD", &idx); cl_number_or_name = argv[idx]->arg; @@ -14505,6 +14908,19 @@ DEFUN (no_ip_extcommunity_list_expanded_all, return CMD_SUCCESS; } +ALIAS (no_extcommunity_list_expanded_all, + no_ip_extcommunity_list_expanded_all_cmd, + "no ip extcommunity-list <(100-500)|expanded WORD> LINE...", + NO_STR + IP_STR + EXTCOMMUNITY_LIST_STR + "Extended Community list number (expanded)\n" + "Specify expanded extcommunity-list\n" + "Extended Community list name\n" + "Specify community to reject\n" + "Specify community to accept\n" + "An ordered list as a regular-expression\n") + static void extcommunity_list_show(struct vty *vty, struct community_list *list) { struct community_entry *entry; @@ -14535,16 +14951,23 @@ static void extcommunity_list_show(struct vty *vty, struct community_list *list) } } -DEFUN (show_ip_extcommunity_list, - show_ip_extcommunity_list_cmd, - "show ip extcommunity-list", +DEFUN (show_extcommunity_list, + show_bgp_extcommunity_list_cmd, + "show bgp extcommunity-list", SHOW_STR - IP_STR + BGP_STR "List extended-community list\n") { struct community_list *list; struct community_list_master *cm; + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used"); + } cm = community_list_master_lookup(bgp_clist, EXTCOMMUNITY_LIST_MASTER); if (!cm) return CMD_SUCCESS; @@ -14558,18 +14981,32 @@ DEFUN (show_ip_extcommunity_list, return CMD_SUCCESS; } -DEFUN (show_ip_extcommunity_list_arg, - show_ip_extcommunity_list_arg_cmd, - "show ip extcommunity-list <(1-500)|WORD>", +ALIAS (show_extcommunity_list, + show_ip_extcommunity_list_cmd, + "show ip extcommunity-list", SHOW_STR IP_STR + "List extended-community list\n") + +DEFUN (show_extcommunity_list_arg, + show_bgp_extcommunity_list_arg_cmd, + "show bgp extcommunity-list <(1-500)|WORD>", + SHOW_STR + BGP_STR "List extended-community list\n" "Extcommunity-list number\n" "Extcommunity-list name\n") { int idx_comm_list = 3; struct community_list *list; + int idx = 0; + if (argv_find(argv, argc, "ip", &idx)) { + vty_out(vty, "This config option is deprecated, and is scheduled for removal.\n"); + vty_out(vty, "if you are using this please migrate to the below command.\n"); + vty_out(vty, "'show bgp extcommunity-list <(1-500)|WORD>'\n"); + zlog_warn("Deprecated option: 'ip show extcommunity-list <(1-500)|WORD>' being used"); + } list = community_list_lookup(bgp_clist, argv[idx_comm_list]->arg, EXTCOMMUNITY_LIST_MASTER); if (!list) { @@ -14582,6 +15019,15 @@ DEFUN (show_ip_extcommunity_list_arg, return CMD_SUCCESS; } +ALIAS (show_extcommunity_list_arg, + show_ip_extcommunity_list_arg_cmd, + "show ip extcommunity-list <(1-500)|WORD>", + SHOW_STR + IP_STR + "List extended-community list\n" + "Extcommunity-list number\n" + "Extcommunity-list name\n") + /* Display community-list and extcommunity-list configuration. */ static int community_list_config_write(struct vty *vty) { @@ -14595,14 +15041,14 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip community-list %s %s %s\n", list->name, + vty_out(vty, "bgp community-list %s %s %s\n", list->name, community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip community-list %s %s %s %s\n", + vty_out(vty, "bgp community-list %s %s %s %s\n", entry->style == COMMUNITY_LIST_STANDARD ? "standard" : "expanded", @@ -14616,14 +15062,14 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip extcommunity-list %s %s %s\n", + vty_out(vty, "bgp extcommunity-list %s %s %s\n", list->name, community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip extcommunity-list %s %s %s %s\n", + vty_out(vty, "bgp extcommunity-list %s %s %s %s\n", entry->style == EXTCOMMUNITY_LIST_STANDARD ? "standard" : "expanded", @@ -14639,14 +15085,14 @@ static int community_list_config_write(struct vty *vty) for (list = cm->num.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip large-community-list %s %s %s\n", + vty_out(vty, "bgp large-community-list %s %s %s\n", list->name, community_direct_str(entry->direct), community_list_config_str(entry)); write++; } for (list = cm->str.head; list; list = list->next) for (entry = list->head; entry; entry = entry->next) { - vty_out(vty, "ip large-community-list %s %s %s %s\n", + vty_out(vty, "bgp large-community-list %s %s %s %s\n", entry->style == LARGE_COMMUNITY_LIST_STANDARD ? "standard" : "expanded", @@ -14667,6 +15113,12 @@ static void community_list_vty(void) install_node(&community_list_node, community_list_config_write); /* Community-list. */ + install_element(CONFIG_NODE, &bgp_community_list_standard_cmd); + install_element(CONFIG_NODE, &bgp_community_list_expanded_all_cmd); + install_element(CONFIG_NODE, &no_bgp_community_list_standard_all_cmd); + install_element(CONFIG_NODE, &no_bgp_community_list_expanded_all_cmd); + install_element(VIEW_NODE, &show_bgp_community_list_cmd); + install_element(VIEW_NODE, &show_bgp_community_list_arg_cmd); install_element(CONFIG_NODE, &ip_community_list_standard_cmd); install_element(CONFIG_NODE, &ip_community_list_expanded_all_cmd); install_element(CONFIG_NODE, &no_ip_community_list_standard_all_cmd); @@ -14675,6 +15127,12 @@ static void community_list_vty(void) install_element(VIEW_NODE, &show_ip_community_list_arg_cmd); /* Extcommunity-list. */ + install_element(CONFIG_NODE, &bgp_extcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &bgp_extcommunity_list_name_expanded_cmd); + install_element(CONFIG_NODE, &no_bgp_extcommunity_list_standard_all_cmd); + install_element(CONFIG_NODE, &no_bgp_extcommunity_list_expanded_all_cmd); + install_element(VIEW_NODE, &show_bgp_extcommunity_list_cmd); + install_element(VIEW_NODE, &show_bgp_extcommunity_list_arg_cmd); install_element(CONFIG_NODE, &ip_extcommunity_list_standard_cmd); install_element(CONFIG_NODE, &ip_extcommunity_list_name_expanded_cmd); install_element(CONFIG_NODE, &no_ip_extcommunity_list_standard_all_cmd); @@ -14683,6 +15141,21 @@ static void community_list_vty(void) install_element(VIEW_NODE, &show_ip_extcommunity_list_arg_cmd); /* Large Community List */ + install_element(CONFIG_NODE, &bgp_lcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &bgp_lcommunity_list_standard1_cmd); + install_element(CONFIG_NODE, &bgp_lcommunity_list_expanded_cmd); + install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard_cmd); + install_element(CONFIG_NODE, &bgp_lcommunity_list_name_standard1_cmd); + install_element(CONFIG_NODE, &bgp_lcommunity_list_name_expanded_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_all_cmd); + install_element(CONFIG_NODE, + &no_bgp_lcommunity_list_name_expanded_all_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_standard_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_expanded_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_name_standard_cmd); + install_element(CONFIG_NODE, &no_bgp_lcommunity_list_name_expanded_cmd); + install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd); + install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_standard_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_standard1_cmd); install_element(CONFIG_NODE, &ip_lcommunity_list_expanded_cmd); diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 5a5c7c9861..81a5be9d0c 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -925,41 +925,40 @@ bool bgp_zebra_nexthop_set(union sockunion *local, union sockunion *remote, return true; } -static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info, - ifindex_t *ifindex) +static struct in6_addr * +bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex) { struct in6_addr *nexthop = NULL; /* Only global address nexthop exists. */ - if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) { - nexthop = &info->attr->mp_nexthop_global; + if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) { + nexthop = &path->attr->mp_nexthop_global; if (IN6_IS_ADDR_LINKLOCAL(nexthop)) - *ifindex = info->attr->nh_ifindex; - + *ifindex = path->attr->nh_ifindex; } /* If both global and link-local address present. */ - if (info->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { + if (path->attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) { /* Check if route-map is set to prefer global over link-local */ - if (info->attr->mp_nexthop_prefer_global) { - nexthop = &info->attr->mp_nexthop_global; + if (path->attr->mp_nexthop_prefer_global) { + nexthop = &path->attr->mp_nexthop_global; if (IN6_IS_ADDR_LINKLOCAL(nexthop)) - *ifindex = info->attr->nh_ifindex; + *ifindex = path->attr->nh_ifindex; } else { /* Workaround for Cisco's nexthop bug. */ if (IN6_IS_ADDR_UNSPECIFIED( - &info->attr->mp_nexthop_global) - && info->peer->su_remote->sa.sa_family + &path->attr->mp_nexthop_global) + && path->peer->su_remote->sa.sa_family == AF_INET6) { nexthop = - &info->peer->su_remote->sin6.sin6_addr; + &path->peer->su_remote->sin6.sin6_addr; if (IN6_IS_ADDR_LINKLOCAL(nexthop)) - *ifindex = info->peer->nexthop.ifp + *ifindex = path->peer->nexthop.ifp ->ifindex; } else { - nexthop = &info->attr->mp_nexthop_local; + nexthop = &path->attr->mp_nexthop_local; if (IN6_IS_ADDR_LINKLOCAL(nexthop)) - *ifindex = info->attr->nh_lla_ifindex; + *ifindex = path->attr->nh_lla_ifindex; } } } @@ -968,12 +967,12 @@ static struct in6_addr *bgp_info_to_ipv6_nexthop(struct bgp_info *info, } static int bgp_table_map_apply(struct route_map *map, struct prefix *p, - struct bgp_info *info) + struct bgp_path_info *path) { route_map_result_t ret; - ret = route_map_apply(map, p, RMAP_BGP, info); - bgp_attr_flush(info->attr); + ret = route_map_apply(map, p, RMAP_BGP, path); + bgp_attr_flush(path->attr); if (ret != RMAP_DENYMATCH) return 1; @@ -986,7 +985,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, inet_ntop(AF_INET, &p->u.prefix4, buf[0], sizeof(buf[0])), p->prefixlen, - inet_ntop(AF_INET, &info->attr->nexthop, buf[1], + inet_ntop(AF_INET, &path->attr->nexthop, buf[1], sizeof(buf[1]))); } if (p->family == AF_INET6) { @@ -994,7 +993,7 @@ static int bgp_table_map_apply(struct route_map *map, struct prefix *p, ifindex_t ifindex; struct in6_addr *nexthop; - nexthop = bgp_info_to_ipv6_nexthop(info, &ifindex); + nexthop = bgp_path_info_to_ipv6_nexthop(path, &ifindex); zlog_debug( "Zebra rmap deny: IPv6 route %s/%d nexthop %s", inet_ntop(AF_INET6, &p->u.prefix6, buf[0], @@ -1121,17 +1120,15 @@ static int update_ipv4nh_for_route_install(int nh_othervrf, return 1; } -static int update_ipv6nh_for_route_install(int nh_othervrf, - struct in6_addr *nexthop, - ifindex_t ifindex, - struct bgp_info *ri, - struct bgp_info *best_ri, - bool is_evpn, - struct zapi_nexthop *api_nh) +static int +update_ipv6nh_for_route_install(int nh_othervrf, struct in6_addr *nexthop, + ifindex_t ifindex, struct bgp_path_info *pi, + struct bgp_path_info *best_pi, bool is_evpn, + struct zapi_nexthop *api_nh) { struct attr *attr; - attr = ri->attr; + attr = pi->attr; if (is_evpn) api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; @@ -1150,22 +1147,22 @@ static int update_ipv6nh_for_route_install(int nh_othervrf, } } else { if (IN6_IS_ADDR_LINKLOCAL(nexthop)) { - if (ri == best_ri && - attr->mp_nexthop_len - == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) - if (ri->peer->nexthop.ifp) - ifindex = ri->peer->nexthop.ifp - ->ifindex; + if (pi == best_pi + && attr->mp_nexthop_len + == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) + if (pi->peer->nexthop.ifp) + ifindex = + pi->peer->nexthop.ifp->ifindex; if (!ifindex) { - if (ri->peer->conf_if) - ifindex = ri->peer->ifp->ifindex; - else if (ri->peer->ifname) + if (pi->peer->conf_if) + ifindex = pi->peer->ifp->ifindex; + else if (pi->peer->ifname) ifindex = ifname2ifindex( - ri->peer->ifname, - ri->peer->bgp->vrf_id); - else if (ri->peer->nexthop.ifp) - ifindex = ri->peer->nexthop.ifp - ->ifindex; + pi->peer->ifname, + pi->peer->bgp->vrf_id); + else if (pi->peer->nexthop.ifp) + ifindex = + pi->peer->nexthop.ifp->ifindex; } if (ifindex == 0) @@ -1183,7 +1180,7 @@ static int update_ipv6nh_for_route_install(int nh_othervrf, } void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, - struct bgp_info *info, struct bgp *bgp, afi_t afi, + struct bgp_path_info *info, struct bgp *bgp, afi_t afi, safi_t safi) { struct zapi_route api; @@ -1193,11 +1190,11 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, int has_valid_label = 0; uint8_t distance; struct peer *peer; - struct bgp_info *mpinfo; + struct bgp_path_info *mpinfo; uint32_t metric; struct attr local_attr; - struct bgp_info local_info; - struct bgp_info *mpinfo_cp = &local_info; + struct bgp_path_info local_info; + struct bgp_path_info *mpinfo_cp = &local_info; route_tag_t tag; mpls_label_t label; int nh_othervrf = 0; @@ -1242,7 +1239,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, /* Obtain peer from parent */ if (info->extra && info->extra->parent) - peer = ((struct bgp_info *)(info->extra->parent))->peer; + peer = ((struct bgp_path_info *)(info->extra->parent)) + ->peer; } tag = info->attr->tag; @@ -1266,7 +1264,7 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, /* Metric is currently based on the best-path only */ metric = info->attr->med; - for (mpinfo = info; mpinfo; mpinfo = bgp_info_mpath_next(mpinfo)) { + for (mpinfo = info; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) { if (valid_nh_count >= multipath_num) break; @@ -1356,8 +1354,8 @@ void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, tag = mpinfo_cp->attr->tag; } } - nexthop = bgp_info_to_ipv6_nexthop(mpinfo_cp, - &ifindex); + nexthop = bgp_path_info_to_ipv6_nexthop(mpinfo_cp, + &ifindex); nh_updated = update_ipv6nh_for_route_install( nh_othervrf, nexthop, ifindex, mpinfo, info, is_evpn, api_nh); @@ -1466,7 +1464,7 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) { struct bgp_node *rn; struct bgp_table *table; - struct bgp_info *ri; + struct bgp_path_info *pi; /* Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. @@ -1479,18 +1477,18 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) return; for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) - for (ri = rn->info; ri; ri = ri->next) - if (CHECK_FLAG(ri->flags, BGP_INFO_SELECTED) && + for (pi = rn->info; pi; pi = pi->next) + if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && - (ri->type == ZEBRA_ROUTE_BGP - && (ri->sub_type == BGP_ROUTE_NORMAL - || ri->sub_type == BGP_ROUTE_IMPORTED))) + (pi->type == ZEBRA_ROUTE_BGP + && (pi->sub_type == BGP_ROUTE_NORMAL + || pi->sub_type == BGP_ROUTE_IMPORTED))) - bgp_zebra_announce(rn, &rn->p, ri, bgp, afi, + bgp_zebra_announce(rn, &rn->p, pi, bgp, afi, safi); } -void bgp_zebra_withdraw(struct prefix *p, struct bgp_info *info, +void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *info, struct bgp *bgp, safi_t safi) { struct zapi_route api; @@ -1662,7 +1660,8 @@ int bgp_redistribute_resend(struct bgp *bgp, afi_t afi, int type, } /* Redistribute with route-map specification. */ -int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name) +int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, + struct route_map *route_map) { if (red->rmap.name && (strcmp(red->rmap.name, name) == 0)) return 0; @@ -1670,7 +1669,7 @@ int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name) if (red->rmap.name) XFREE(MTYPE_ROUTE_MAP_NAME, red->rmap.name); red->rmap.name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, name); - red->rmap.map = route_map_lookup_by_name(name); + red->rmap.map = route_map; return 1; } @@ -1680,7 +1679,7 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, afi_t afi, int type, uint32_t metric) { struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *pi; if (red->redist_metric_flag && red->redist_metric == metric) return 0; @@ -1690,21 +1689,21 @@ int bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red, for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - for (ri = rn->info; ri; ri = ri->next) { - if (ri->sub_type == BGP_ROUTE_REDISTRIBUTE - && ri->type == type - && ri->instance == red->instance) { + for (pi = rn->info; pi; pi = pi->next) { + if (pi->sub_type == BGP_ROUTE_REDISTRIBUTE + && pi->type == type + && pi->instance == red->instance) { struct attr *old_attr; struct attr new_attr; - bgp_attr_dup(&new_attr, ri->attr); + bgp_attr_dup(&new_attr, pi->attr); new_attr.med = red->redist_metric; - old_attr = ri->attr; - ri->attr = bgp_attr_intern(&new_attr); + old_attr = pi->attr; + pi->attr = bgp_attr_intern(&new_attr); bgp_attr_unintern(&old_attr); - bgp_info_set_flag(rn, ri, - BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(rn, pi, + BGP_PATH_ATTR_CHANGED); bgp_process(bgp, rn, afi, SAFI_UNICAST); } } @@ -1933,6 +1932,29 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni) return zclient_send_message(zclient); } +int bgp_zebra_vxlan_flood_control(struct bgp *bgp, + enum vxlan_flood_control flood_ctrl) +{ + struct stream *s; + + /* Check socket. */ + if (!zclient || zclient->sock < 0) + return 0; + + /* Don't try to register if Zebra doesn't know of this instance. */ + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + return 0; + + s = zclient->obuf; + stream_reset(s); + + zclient_create_header(s, ZEBRA_VXLAN_FLOOD_CONTROL, bgp->vrf_id); + stream_putc(s, flood_ctrl); + stream_putw_at(s, 0, stream_get_endp(s)); + + return zclient_send_message(zclient); +} + int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise) { struct stream *s; @@ -1950,6 +1972,10 @@ int bgp_zebra_advertise_all_vni(struct bgp *bgp, int advertise) zclient_create_header(s, ZEBRA_ADVERTISE_ALL_VNI, bgp->vrf_id); stream_putc(s, advertise); + /* Also inform current BUM handling setting. This is really + * relevant only when 'advertise' is set. + */ + stream_putc(s, bgp->vxlan_flood_ctrl); stream_putw_at(s, 0, stream_get_endp(s)); return zclient_send_message(zclient); @@ -2081,20 +2107,20 @@ static int ipset_entry_notify_owner(int command, struct zclient *zclient, break; case ZAPI_IPSET_ENTRY_INSTALLED: { - struct bgp_info *bgp_info; - struct bgp_info_extra *extra; + struct bgp_path_info *path; + struct bgp_path_info_extra *extra; - bgp_pbime->installed = true; - bgp_pbime->install_in_progress = false; - if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%s: Received IPSET_ENTRY_INSTALLED", - __PRETTY_FUNCTION__); - /* link bgp_info to bpme */ - bgp_info = (struct bgp_info *)bgp_pbime->bgp_info; - extra = bgp_info_extra_get(bgp_info); - if (extra->bgp_fs_pbr == NULL) - extra->bgp_fs_pbr = list_new(); - listnode_add(extra->bgp_fs_pbr, bgp_pbime); + bgp_pbime->installed = true; + bgp_pbime->install_in_progress = false; + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: Received IPSET_ENTRY_INSTALLED", + __PRETTY_FUNCTION__); + /* link bgp_path_info to bpme */ + path = (struct bgp_path_info *)bgp_pbime->path; + extra = bgp_path_info_extra_get(path); + if (extra->bgp_fs_pbr == NULL) + extra->bgp_fs_pbr = list_new(); + listnode_add(extra->bgp_fs_pbr, bgp_pbime); } break; case ZAPI_IPSET_ENTRY_FAIL_REMOVE: diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 0223c423df..2ea1fc777c 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -36,11 +36,12 @@ extern void bgp_config_write_maxpaths(struct vty *, struct bgp *, afi_t, safi_t); extern void bgp_config_write_redistribute(struct vty *, struct bgp *, afi_t, safi_t); -extern void bgp_zebra_announce(struct bgp_node *, struct prefix *, - struct bgp_info *, struct bgp *, afi_t, safi_t); +extern void bgp_zebra_announce(struct bgp_node *rn, struct prefix *p, + struct bgp_path_info *path, struct bgp *bgp, + afi_t afi, safi_t safi); extern void bgp_zebra_announce_table(struct bgp *, afi_t, safi_t); -extern void bgp_zebra_withdraw(struct prefix *, struct bgp_info *, - struct bgp *, safi_t); +extern void bgp_zebra_withdraw(struct prefix *p, struct bgp_path_info *path, + struct bgp *bgp, safi_t safi); extern void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer); extern void bgp_zebra_terminate_radv(struct bgp *bgp, struct peer *peer); @@ -55,7 +56,8 @@ extern struct bgp_redist *bgp_redist_add(struct bgp *, afi_t, uint8_t, extern int bgp_redistribute_set(struct bgp *, afi_t, int, unsigned short, bool changed); extern int bgp_redistribute_resend(struct bgp *, afi_t, int, unsigned short); -extern int bgp_redistribute_rmap_set(struct bgp_redist *, const char *); +extern int bgp_redistribute_rmap_set(struct bgp_redist *red, const char *name, + struct route_map *route_map); extern int bgp_redistribute_metric_set(struct bgp *, struct bgp_redist *, afi_t, int, uint32_t); extern int bgp_redistribute_unset(struct bgp *, afi_t, int, unsigned short); @@ -71,6 +73,8 @@ extern int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni); extern int bgp_zebra_advertise_gw_macip(struct bgp *, int, vni_t); extern int bgp_zebra_advertise_all_vni(struct bgp *, int); +extern int bgp_zebra_vxlan_flood_control(struct bgp *bgp, + enum vxlan_flood_control flood_ctrl); extern int bgp_zebra_num_connects(void); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 0300485e91..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; @@ -1422,7 +1422,15 @@ void bgp_recalculate_all_bestpaths(struct bgp *bgp) } } -/* Create new BGP peer. */ +/* + * Create new BGP peer. + * + * conf_if and su are mutually exclusive if configuring from the cli. + * If we are handing a doppelganger, then we *must* pass in both + * the original peer's su and conf_if, so that we can appropriately + * track the bgp->peerhash( ie we don't want to remove the current + * one from the config ). + */ struct peer *peer_create(union sockunion *su, const char *conf_if, struct bgp *bgp, as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi, @@ -1435,7 +1443,10 @@ struct peer *peer_create(union sockunion *su, const char *conf_if, peer = peer_new(bgp); if (conf_if) { peer->conf_if = XSTRDUP(MTYPE_PEER_CONF_IF, conf_if); - bgp_peer_conf_if_to_su_update(peer); + if (su) + peer->su = *su; + else + bgp_peer_conf_if_to_su_update(peer); if (peer->host) XFREE(MTYPE_BGP_PEER_HOST, peer->host); peer->host = XSTRDUP(MTYPE_BGP_PEER_HOST, conf_if); @@ -4485,7 +4496,7 @@ int peer_update_source_unset(struct peer *peer) } int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, - const char *rmap) + const char *rmap, struct route_map *route_map) { struct peer *member; struct listnode *node, *nnode; @@ -4501,8 +4512,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, peer->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - peer->default_rmap[afi][safi].map = - route_map_lookup_by_name(rmap); + peer->default_rmap[afi][safi].map = route_map; } } else if (!rmap) { if (peer->default_rmap[afi][safi].name) @@ -4546,8 +4556,7 @@ int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, member->default_rmap[afi][safi].name = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - member->default_rmap[afi][safi].map = - route_map_lookup_by_name(rmap); + member->default_rmap[afi][safi].map = route_map; } /* Update peer route announcements. */ @@ -6012,7 +6021,7 @@ static void peer_aslist_del(const char *aslist_name) int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct, - const char *name) + const char *name, struct route_map *route_map) { struct peer *member; struct bgp_filter *filter; @@ -6026,7 +6035,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct, if (filter->map[direct].name) XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name(name); + filter->map[direct].map = route_map; /* Check if handling a regular peer. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { @@ -6055,7 +6064,7 @@ int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int direct, if (filter->map[direct].name) XFREE(MTYPE_BGP_FILTER_NAME, filter->map[direct].name); filter->map[direct].name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->map[direct].map = route_map_lookup_by_name(name); + filter->map[direct].map = route_map; /* Process peer route updates. */ peer_on_policy_change(member, afi, safi, @@ -6130,7 +6139,7 @@ int peer_route_map_unset(struct peer *peer, afi_t afi, safi_t safi, int direct) /* Set unsuppress-map to the peer. */ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, - const char *name) + const char *name, struct route_map *route_map) { struct peer *member; struct bgp_filter *filter; @@ -6141,7 +6150,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, if (filter->usmap.name) XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name(name); + filter->usmap.map = route_map; /* Check if handling a regular peer. */ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { @@ -6169,7 +6178,7 @@ int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, if (filter->usmap.name) XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name); filter->usmap.name = XSTRDUP(MTYPE_BGP_FILTER_NAME, name); - filter->usmap.map = route_map_lookup_by_name(name); + filter->usmap.map = route_map; /* Process peer route updates. */ peer_on_policy_change(member, afi, safi, 1); @@ -6297,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); @@ -6323,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/bgpd.h b/bgpd/bgpd.h index 861435c036..c04fe69035 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -485,6 +485,11 @@ struct bgp { /* EVPN - use RFC 8365 to auto-derive RT */ int advertise_autort_rfc8365; + /* + * Flooding mechanism for BUM packets for VxLAN-EVPN. + */ + enum vxlan_flood_control vxlan_flood_ctrl; + /* Hash table of Import RTs to EVIs */ struct hash *import_rt_hash; @@ -1605,8 +1610,9 @@ extern int peer_update_source_if_set(struct peer *, const char *); extern int peer_update_source_addr_set(struct peer *, const union sockunion *); extern int peer_update_source_unset(struct peer *); -extern int peer_default_originate_set(struct peer *, afi_t, safi_t, - const char *); +extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi, + const char *rmap, + struct route_map *route_map); extern int peer_default_originate_unset(struct peer *, afi_t, safi_t); extern int peer_port_set(struct peer *, uint16_t); @@ -1644,10 +1650,13 @@ extern int peer_prefix_list_unset(struct peer *, afi_t, safi_t, int); extern int peer_aslist_set(struct peer *, afi_t, safi_t, int, const char *); extern int peer_aslist_unset(struct peer *, afi_t, safi_t, int); -extern int peer_route_map_set(struct peer *, afi_t, safi_t, int, const char *); +extern int peer_route_map_set(struct peer *peer, afi_t afi, safi_t safi, int, + const char *name, struct route_map *route_map); extern int peer_route_map_unset(struct peer *, afi_t, safi_t, int); -extern int peer_unsuppress_map_set(struct peer *, afi_t, safi_t, const char *); +extern int peer_unsuppress_map_set(struct peer *peer, afi_t afi, safi_t safi, + const char *name, + struct route_map *route_map); extern int peer_password_set(struct peer *, const char *); extern int peer_password_unset(struct peer *); 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.c b/bgpd/rfapi/rfapi.c index c7c2239db7..6978dd145d 100644 --- a/bgpd/rfapi/rfapi.c +++ b/bgpd/rfapi/rfapi.c @@ -361,7 +361,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, { afi_t afi; /* of the VN address */ struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; char buf[PREFIX_STRLEN]; char buf2[RD_ADDRSTRLEN]; struct prefix_rd prd0; @@ -384,21 +384,22 @@ void del_vnc_route(struct rfapi_descriptor *rfd, __func__, peer, buf, prefix_rd2str(prd, buf2, sizeof(buf2)), afi, safi, bn, (bn ? bn->info : NULL)); - for (bi = (bn ? bn->info : NULL); bi; bi = bi->next) { + for (bpi = (bn ? bn->info : NULL); bpi; bpi = bpi->next) { vnc_zlog_debug_verbose( - "%s: trying bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p, local_pref=%u", - __func__, bi, bi->peer, bi->type, bi->sub_type, - (bi->extra ? bi->extra->vnc.export.rfapi_handle : NULL), - ((bi->attr - && CHECK_FLAG(bi->attr->flag, + "%s: trying bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p, local_pref=%u", + __func__, bpi, bpi->peer, bpi->type, bpi->sub_type, + (bpi->extra ? bpi->extra->vnc.export.rfapi_handle + : NULL), + ((bpi->attr + && CHECK_FLAG(bpi->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) - ? bi->attr->local_pref + ? bpi->attr->local_pref : 0)); - if (bi->peer == peer && bi->type == type - && bi->sub_type == sub_type && bi->extra - && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + if (bpi->peer == peer && bpi->type == type + && bpi->sub_type == sub_type && bpi->extra + && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) { vnc_zlog_debug_verbose("%s: matched it", __func__); @@ -412,8 +413,8 @@ void del_vnc_route(struct rfapi_descriptor *rfd, * route. Leave the route itself in place. * TBD add return code reporting of success/failure */ - if (!bi || !bi->extra - || !bi->extra->vnc.export.local_nexthops) { + if (!bpi || !bpi->extra + || !bpi->extra->vnc.export.local_nexthops) { /* * no local nexthops */ @@ -429,7 +430,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, struct listnode *node; struct rfapi_nexthop *pLnh = NULL; - for (ALL_LIST_ELEMENTS_RO(bi->extra->vnc.export.local_nexthops, + for (ALL_LIST_ELEMENTS_RO(bpi->extra->vnc.export.local_nexthops, node, pLnh)) { if (prefix_same(&pLnh->addr, &lnh->addr)) { @@ -438,7 +439,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, } if (pLnh) { - listnode_delete(bi->extra->vnc.export.local_nexthops, + listnode_delete(bpi->extra->vnc.export.local_nexthops, pLnh); /* silly rabbit, listnode_delete doesn't invoke @@ -458,7 +459,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, */ rfapiProcessWithdraw(peer, rfd, p, prd, NULL, afi, safi, type, kill); - if (bi) { + if (bpi) { prefix2str(p, buf, sizeof(buf)); vnc_zlog_debug_verbose( "%s: Found route (safi=%d) to delete at prefix %s", @@ -474,7 +475,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd, table = (struct bgp_table *)(prn->info); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - bgp, prd, table, p, bi); + bgp, prd, table, p, bpi); } bgp_unlock_node(prn); } @@ -482,13 +483,11 @@ void del_vnc_route(struct rfapi_descriptor *rfd, /* * Delete local_nexthops list */ - if (bi->extra && bi->extra->vnc.export.local_nexthops) { - list_delete( - &bi->extra->vnc.export.local_nexthops); - } + if (bpi->extra && bpi->extra->vnc.export.local_nexthops) + list_delete(&bpi->extra->vnc.export.local_nexthops); - bgp_aggregate_decrement(bgp, p, bi, afi, safi); - bgp_info_delete(bn, bi); + bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + bgp_path_info_delete(bn, bpi); bgp_process(bgp, bn, afi, safi); } else { vnc_zlog_debug_verbose( @@ -575,8 +574,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ int flags) { afi_t afi; /* of the VN address */ - struct bgp_info *new; - struct bgp_info *bi; + struct bgp_path_info *new; + struct bgp_path_info *bpi; struct bgp_node *bn; struct attr attr = {0}; @@ -946,29 +945,29 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ * ecommunity: POINTS TO interned/refcounted dynamic 2-part AS attr * aspath: POINTS TO interned/refcounted hashed block */ - for (bi = bn->info; bi; bi = bi->next) { + for (bpi = bn->info; bpi; bpi = bpi->next) { /* probably only need to check - * bi->extra->vnc.export.rfapi_handle */ - if (bi->peer == rfd->peer && bi->type == type - && bi->sub_type == sub_type && bi->extra - && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + * bpi->extra->vnc.export.rfapi_handle */ + if (bpi->peer == rfd->peer && bpi->type == type + && bpi->sub_type == sub_type && bpi->extra + && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) { break; } } - if (bi) { + if (bpi) { /* * Adding new local_nexthop, which does not by itself change * what is advertised via BGP */ if (lnh) { - if (!bi->extra->vnc.export.local_nexthops) { + if (!bpi->extra->vnc.export.local_nexthops) { /* TBD make arrangements to free when needed */ - bi->extra->vnc.export.local_nexthops = + bpi->extra->vnc.export.local_nexthops = list_new(); - bi->extra->vnc.export.local_nexthops->del = + bpi->extra->vnc.export.local_nexthops->del = rfapi_nexthop_free; } @@ -979,8 +978,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ struct rfapi_nexthop *pLnh = NULL; for (ALL_LIST_ELEMENTS_RO( - bi->extra->vnc.export.local_nexthops, node, - pLnh)) { + bpi->extra->vnc.export.local_nexthops, + node, pLnh)) { if (prefix_same(&pLnh->addr, &lnh->addr)) { break; @@ -993,13 +992,13 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ if (!pLnh) { pLnh = rfapi_nexthop_new(lnh); listnode_add( - bi->extra->vnc.export.local_nexthops, + bpi->extra->vnc.export.local_nexthops, pLnh); } } - if (attrhash_cmp(bi->attr, new_attr) - && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (attrhash_cmp(bpi->attr, new_attr) + && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { bgp_attr_unintern(&new_attr); bgp_unlock_node(bn); @@ -1010,7 +1009,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ goto done; } else { /* The attribute is changed. */ - bgp_info_set_flag(bn, bi, BGP_INFO_ATTR_CHANGED); + bgp_path_info_set_flag(bn, bpi, BGP_PATH_ATTR_CHANGED); if (safi == SAFI_MPLS_VPN) { struct bgp_node *prn = NULL; @@ -1022,19 +1021,19 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ table = (struct bgp_table *)(prn->info); vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( - bgp, prd, table, p, bi); + bgp, prd, table, p, bpi); } bgp_unlock_node(prn); } /* Rewrite BGP route information. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) - bgp_info_restore(bn, bi); + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) + bgp_path_info_restore(bn, bpi); else - bgp_aggregate_decrement(bgp, p, bi, afi, safi); - bgp_attr_unintern(&bi->attr); - bi->attr = new_attr; - bi->uptime = bgp_clock(); + bgp_aggregate_decrement(bgp, p, bpi, afi, safi); + bgp_attr_unintern(&bpi->attr); + bpi->attr = new_attr; + bpi->uptime = bgp_clock(); if (safi == SAFI_MPLS_VPN) { @@ -1047,13 +1046,13 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ table = (struct bgp_table *)(prn->info); vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( - bgp, prd, table, p, bi); + bgp, prd, table, p, bpi); } bgp_unlock_node(prn); } /* Process change. */ - bgp_aggregate_increment(bgp, p, bi, afi, safi); + bgp_aggregate_increment(bgp, p, bpi, afi, safi); bgp_process(bgp, bn, afi, safi); bgp_unlock_node(bn); @@ -1066,16 +1065,16 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ } - new = bgp_info_new(); + new = bgp_path_info_new(); new->type = type; new->sub_type = sub_type; new->peer = rfd->peer; - SET_FLAG(new->flags, BGP_INFO_VALID); + SET_FLAG(new->flags, BGP_PATH_VALID); new->attr = new_attr; new->uptime = bgp_clock(); /* save backref to rfapi handle */ - assert(bgp_info_extra_get(new)); + assert(bgp_path_info_extra_get(new)); new->extra->vnc.export.rfapi_handle = (void *)rfd; encode_label(label_val, &new->extra->label[0]); @@ -1087,7 +1086,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */ } bgp_aggregate_increment(bgp, p, new, afi, safi); - bgp_info_add(bn, new); + bgp_path_info_add(bn, new); if (safi == SAFI_MPLS_VPN) { struct bgp_node *prn = NULL; @@ -3690,7 +3689,7 @@ static void rfapi_print_exported(struct bgp *bgp) { struct bgp_node *rdn; struct bgp_node *rn; - struct bgp_info *bi; + struct bgp_path_info *bpi; if (!bgp) return; @@ -3705,8 +3704,8 @@ static void rfapi_print_exported(struct bgp *bgp) if (!rn->info) continue; fprintf(stderr, "%s: rn=%p\n", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) { - rfapiPrintBi((void *)2, bi); /* 2 => stderr */ + for (bpi = rn->info; bpi; bpi = bpi->next) { + rfapiPrintBi((void *)2, bpi); /* 2 => stderr */ } } } @@ -3720,8 +3719,8 @@ static void rfapi_print_exported(struct bgp *bgp) if (!rn->info) continue; fprintf(stderr, "%s: rn=%p\n", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) { - rfapiPrintBi((void *)2, bi); /* 2 => stderr */ + for (bpi = rn->info; bpi; bpi = bpi->next) { + rfapiPrintBi((void *)2, bpi); /* 2 => stderr */ } } } diff --git a/bgpd/rfapi/rfapi_backend.h b/bgpd/rfapi/rfapi_backend.h index bcd894b884..96e464d2ae 100644 --- a/bgpd/rfapi/rfapi_backend.h +++ b/bgpd/rfapi/rfapi_backend.h @@ -48,14 +48,16 @@ extern void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p, extern void rfapiProcessPeerDown(struct peer *peer); -extern void vnc_zebra_announce(struct prefix *p, struct bgp_info *new_select, +extern void vnc_zebra_announce(struct prefix *p, + struct bgp_path_info *new_select, struct bgp *bgp); -extern void vnc_zebra_withdraw(struct prefix *p, struct bgp_info *old_select); +extern void vnc_zebra_withdraw(struct prefix *p, + struct bgp_path_info *old_select); extern void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, - struct bgp_info *bi, safi_t safi); + struct bgp_path_info *bpi, safi_t safi); extern void vnc_direct_bgp_vpn_enable(struct bgp *bgp, afi_t afi); diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c index 398de6b3a1..6f5af5182a 100644 --- a/bgpd/rfapi/rfapi_import.c +++ b/bgpd/rfapi/rfapi_import.c @@ -79,7 +79,7 @@ struct rfapi_withdraw { struct rfapi_import_table *import_table; struct agg_node *node; - struct bgp_info *info; + struct bgp_path_info *info; safi_t safi; /* used only for bulk operations */ /* * For import table node reference count checking (i.e., debugging). @@ -150,22 +150,22 @@ void rfapiCheckRouteCount() for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { - struct bgp_info *bi; - struct bgp_info *next; + struct bgp_path_info *bpi; + struct bgp_path_info *next; - for (bi = rn->info; bi; bi = next) { - next = bi->next; + for (bpi = rn->info; bpi; bpi = next) { + next = bpi->next; - if (CHECK_FLAG(bi->flags, - BGP_INFO_REMOVED)) { + if (CHECK_FLAG(bpi->flags, + BGP_PATH_REMOVED)) { ++holddown_count; } else { - if (RFAPI_LOCAL_BI(bi)) { + if (RFAPI_LOCAL_BI(bpi)) { ++local_count; } else { if (RFAPI_DIRECT_IMPORT_BI( - bi)) { + bpi)) { ++imported_count; } else { ++remote_count; @@ -216,14 +216,14 @@ void rfapiCheckRouteCount() */ void rfapiCheckRefcount(struct agg_node *rn, safi_t safi, int lockoffset) { - unsigned int count_bi = 0; + unsigned int count_bpi = 0; unsigned int count_monitor = 0; - struct bgp_info *bi; + struct bgp_path_info *bpi; struct rfapi_monitor_encap *hme; struct rfapi_monitor_vpn *hmv; - for (bi = rn->info; bi; bi = bi->next) - ++count_bi; + for (bpi = rn->info; bpi; bpi = bpi->next) + ++count_bpi; if (rn->aggregate) { @@ -265,10 +265,10 @@ void rfapiCheckRefcount(struct agg_node *rn, safi_t safi, int lockoffset) } } - if (count_bi + count_monitor + lockoffset != rn->lock) { + if (count_bpi + count_monitor + lockoffset != rn->lock) { vnc_zlog_debug_verbose( - "%s: count_bi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d", - __func__, count_bi, count_monitor, lockoffset, + "%s: count_bpi=%d, count_monitor=%d, lockoffset=%d, rn->lock=%d", + __func__, count_bpi, count_monitor, lockoffset, rn->lock); assert(0); } @@ -457,28 +457,28 @@ int rfapiGetVncTunnelUnAddr(struct attr *attr, struct prefix *p) /* * Get UN address wherever it might be */ -int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p) +int rfapiGetUnAddrOfVpnBi(struct bgp_path_info *bpi, struct prefix *p) { /* If it's in this route's VNC attribute, we're done */ - if (!rfapiGetVncTunnelUnAddr(bi->attr, p)) + if (!rfapiGetVncTunnelUnAddr(bpi->attr, p)) return 0; /* * Otherwise, see if it's cached from a corresponding ENCAP SAFI * advertisement */ - if (bi->extra) { - switch (bi->extra->vnc.import.un_family) { + if (bpi->extra) { + switch (bpi->extra->vnc.import.un_family) { case AF_INET: if (p) { - p->family = bi->extra->vnc.import.un_family; - p->u.prefix4 = bi->extra->vnc.import.un.addr4; + p->family = bpi->extra->vnc.import.un_family; + p->u.prefix4 = bpi->extra->vnc.import.un.addr4; p->prefixlen = 32; } return 0; case AF_INET6: if (p) { - p->family = bi->extra->vnc.import.un_family; - p->u.prefix6 = bi->extra->vnc.import.un.addr6; + p->family = bpi->extra->vnc.import.un_family; + p->u.prefix6 = bpi->extra->vnc.import.un.addr6; p->prefixlen = 128; } return 0; @@ -487,7 +487,7 @@ int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p) p->family = 0; #if DEBUG_ENCAP_MONITOR vnc_zlog_debug_verbose( - "%s: bi->extra->vnc.import.un_family is 0, no UN addr", + "%s: bpi->extra->vnc.import.un_family is 0, no UN addr", __func__); #endif break; @@ -499,23 +499,24 @@ int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p) /* - * Make a new bgp_info from gathered parameters + * Make a new bgp_path_info from gathered parameters */ -static struct bgp_info *rfapiBgpInfoCreate(struct attr *attr, struct peer *peer, - void *rfd, struct prefix_rd *prd, - uint8_t type, uint8_t sub_type, - uint32_t *label) +static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr, + struct peer *peer, void *rfd, + struct prefix_rd *prd, + uint8_t type, uint8_t sub_type, + uint32_t *label) { - struct bgp_info *new; + struct bgp_path_info *new; - new = bgp_info_new(); + new = bgp_path_info_new(); assert(new); if (attr) { if (!new->attr) new->attr = bgp_attr_intern(attr); } - bgp_info_extra_get(new); + bgp_path_info_extra_get(new); if (prd) { new->extra->vnc.import.rd = *prd; rfapi_time(&new->extra->vnc.import.create_time); @@ -531,10 +532,10 @@ static struct bgp_info *rfapiBgpInfoCreate(struct attr *attr, struct peer *peer, } /* - * Frees bgp_info as used in import tables (parts are not + * Frees bgp_path_info as used in import tables (parts are not * allocated exactly the way they are in the main RIBs) */ -static void rfapiBgpInfoFree(struct bgp_info *goner) +static void rfapiBgpInfoFree(struct bgp_path_info *goner) { if (!goner) return; @@ -634,7 +635,7 @@ struct rfapi_import_table *rfapiMacImportTableGet(struct bgp *bgp, uint32_t lni) static struct rfapi_monitor_vpn * rfapiMonitorMoveShorter(struct agg_node *original_vpn_node, int lockoffset) { - struct bgp_info *bi; + struct bgp_path_info *bpi; struct agg_node *par; struct rfapi_monitor_vpn *m; struct rfapi_monitor_vpn *mlast; @@ -655,14 +656,14 @@ rfapiMonitorMoveShorter(struct agg_node *original_vpn_node, int lockoffset) #endif /* - * 1. If there is at least one bi (either regular route or + * 1. If there is at least one bpi (either regular route or * route marked as withdrawn, with a pending timer) at * original_node with a valid UN address, we're done. Return. */ - for (bi = original_vpn_node->info; bi; bi = bi->next) { + for (bpi = original_vpn_node->info; bpi; bpi = bpi->next) { struct prefix pfx; - if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) { + if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx)) { #if DEBUG_MONITOR_MOVE_SHORTER vnc_zlog_debug_verbose( "%s: have valid UN at original node, no change", @@ -680,13 +681,13 @@ rfapiMonitorMoveShorter(struct agg_node *original_vpn_node, int lockoffset) */ for (par = agg_node_parent(original_vpn_node); par; par = agg_node_parent(par)) { - for (bi = par->info; bi; bi = bi->next) { + for (bpi = par->info; bpi; bpi = bpi->next) { struct prefix pfx; - if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) { + if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx)) { break; } } - if (bi) + if (bpi) break; } @@ -801,7 +802,7 @@ static void rfapiMonitorMoveLonger(struct agg_node *new_vpn_node) { struct rfapi_monitor_vpn *monitor; struct rfapi_monitor_vpn *mlast; - struct bgp_info *bi; + struct bgp_path_info *bpi; struct agg_node *par; RFAPI_CHECK_REFCOUNT(new_vpn_node, SAFI_MPLS_VPN, 0); @@ -809,13 +810,13 @@ static void rfapiMonitorMoveLonger(struct agg_node *new_vpn_node) /* * Make sure we have at least one valid route at the new node */ - for (bi = new_vpn_node->info; bi; bi = bi->next) { + for (bpi = new_vpn_node->info; bpi; bpi = bpi->next) { struct prefix pfx; - if (!rfapiGetUnAddrOfVpnBi(bi, &pfx)) + if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx)) break; } - if (!bi) { + if (!bpi) { vnc_zlog_debug_verbose( "%s: no valid routes at node %p, so not attempting moves", __func__, new_vpn_node); @@ -881,31 +882,31 @@ static void rfapiMonitorMoveLonger(struct agg_node *new_vpn_node) } -static void rfapiBgpInfoChainFree(struct bgp_info *bi) +static void rfapiBgpInfoChainFree(struct bgp_path_info *bpi) { - struct bgp_info *next; + struct bgp_path_info *next; - while (bi) { + while (bpi) { /* - * If there is a timer waiting to delete this bi, cancel + * If there is a timer waiting to delete this bpi, cancel * the timer and delete immediately */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) - && bi->extra->vnc.import.timer) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) + && bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi->extra->vnc.import.timer; + (struct thread *)bpi->extra->vnc.import.timer; struct rfapi_withdraw *wcb = t->arg; XFREE(MTYPE_RFAPI_WITHDRAW, wcb); thread_cancel(t); } - next = bi->next; - bi->next = NULL; - rfapiBgpInfoFree(bi); - bi = next; + next = bpi->next; + bpi->next = NULL; + rfapiBgpInfoFree(bpi); + bpi = next; } } @@ -929,9 +930,9 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it) * Each route_node has: * aggregate: points to rfapi_it_extra with monitor * chain(s) - * info: points to chain of bgp_info + * info: points to chain of bgp_path_info */ - /* free bgp_info and its children */ + /* free bgp_path_info and its children */ rfapiBgpInfoChainFree(rn->info); rn->info = NULL; @@ -940,7 +941,7 @@ static void rfapiImportTableFlush(struct rfapi_import_table *it) for (rn = agg_route_top(it->imported_encap[afi]); rn; rn = agg_route_next(rn)) { - /* free bgp_info and its children */ + /* free bgp_path_info and its children */ rfapiBgpInfoChainFree(rn->info); rn->info = NULL; @@ -1100,27 +1101,28 @@ int rfapiEcommunityGetEthernetTag(struct ecommunity *ecom, uint16_t *tag_id) return ENOENT; } -static int rfapiVpnBiNhEqualsPt(struct bgp_info *bi, struct rfapi_ip_addr *hpt) +static int rfapiVpnBiNhEqualsPt(struct bgp_path_info *bpi, + struct rfapi_ip_addr *hpt) { uint8_t family; - if (!hpt || !bi) + if (!hpt || !bpi) return 0; - family = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len); + family = BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len); if (hpt->addr_family != family) return 0; switch (family) { case AF_INET: - if (bi->attr->mp_nexthop_global_in.s_addr + if (bpi->attr->mp_nexthop_global_in.s_addr != hpt->addr.v4.s_addr) return 0; break; case AF_INET6: - if (IPV6_ADDR_CMP(&bi->attr->mp_nexthop_global, &hpt->addr.v6)) + if (IPV6_ADDR_CMP(&bpi->attr->mp_nexthop_global, &hpt->addr.v6)) return 0; break; @@ -1136,36 +1138,37 @@ static int rfapiVpnBiNhEqualsPt(struct bgp_info *bi, struct rfapi_ip_addr *hpt) /* * Compare 2 VPN BIs. Return true if they have the same VN and UN addresses */ -static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2) +static int rfapiVpnBiSamePtUn(struct bgp_path_info *bpi1, + struct bgp_path_info *bpi2) { struct prefix pfx_un1; struct prefix pfx_un2; - if (!bi1 || !bi2) + if (!bpi1 || !bpi2) return 0; - if (!bi1->attr || !bi2->attr) + if (!bpi1->attr || !bpi2->attr) return 0; /* * VN address comparisons */ - if (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len) - != BGP_MP_NEXTHOP_FAMILY(bi2->attr->mp_nexthop_len)) { + if (BGP_MP_NEXTHOP_FAMILY(bpi1->attr->mp_nexthop_len) + != BGP_MP_NEXTHOP_FAMILY(bpi2->attr->mp_nexthop_len)) { return 0; } - switch (BGP_MP_NEXTHOP_FAMILY(bi1->attr->mp_nexthop_len)) { + switch (BGP_MP_NEXTHOP_FAMILY(bpi1->attr->mp_nexthop_len)) { case AF_INET: - if (bi1->attr->mp_nexthop_global_in.s_addr - != bi2->attr->mp_nexthop_global_in.s_addr) + if (bpi1->attr->mp_nexthop_global_in.s_addr + != bpi2->attr->mp_nexthop_global_in.s_addr) return 0; break; case AF_INET6: - if (IPV6_ADDR_CMP(&bi1->attr->mp_nexthop_global, - &bi2->attr->mp_nexthop_global)) + if (IPV6_ADDR_CMP(&bpi1->attr->mp_nexthop_global, + &bpi2->attr->mp_nexthop_global)) return 0; break; @@ -1177,17 +1180,17 @@ static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2) /* * UN address comparisons */ - if (rfapiGetVncTunnelUnAddr(bi1->attr, &pfx_un1)) { - if (bi1->extra) { - pfx_un1.family = bi1->extra->vnc.import.un_family; - switch (bi1->extra->vnc.import.un_family) { + if (rfapiGetVncTunnelUnAddr(bpi1->attr, &pfx_un1)) { + if (bpi1->extra) { + pfx_un1.family = bpi1->extra->vnc.import.un_family; + switch (bpi1->extra->vnc.import.un_family) { case AF_INET: pfx_un1.u.prefix4 = - bi1->extra->vnc.import.un.addr4; + bpi1->extra->vnc.import.un.addr4; break; case AF_INET6: pfx_un1.u.prefix6 = - bi1->extra->vnc.import.un.addr6; + bpi1->extra->vnc.import.un.addr6; break; default: pfx_un1.family = 0; @@ -1196,17 +1199,17 @@ static int rfapiVpnBiSamePtUn(struct bgp_info *bi1, struct bgp_info *bi2) } } - if (rfapiGetVncTunnelUnAddr(bi2->attr, &pfx_un2)) { - if (bi2->extra) { - pfx_un2.family = bi2->extra->vnc.import.un_family; - switch (bi2->extra->vnc.import.un_family) { + if (rfapiGetVncTunnelUnAddr(bpi2->attr, &pfx_un2)) { + if (bpi2->extra) { + pfx_un2.family = bpi2->extra->vnc.import.un_family; + switch (bpi2->extra->vnc.import.un_family) { case AF_INET: pfx_un2.u.prefix4 = - bi2->extra->vnc.import.un.addr4; + bpi2->extra->vnc.import.un.addr4; break; case AF_INET6: pfx_un2.u.prefix6 = - bi2->extra->vnc.import.un.addr6; + bpi2->extra->vnc.import.un.addr6; break; default: pfx_un2.family = 0; @@ -1295,15 +1298,15 @@ int rfapi_extract_l2o( static struct rfapi_next_hop_entry * rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, - struct bgp_info *bi, /* route to encode */ - uint32_t lifetime, /* use this in nhe */ - struct agg_node *rn) /* req for L2 eth addr */ + struct bgp_path_info *bpi, /* route to encode */ + uint32_t lifetime, /* use this in nhe */ + struct agg_node *rn) /* req for L2 eth addr */ { struct rfapi_next_hop_entry *new; int have_vnc_tunnel_un = 0; #if DEBUG_ENCAP_MONITOR - vnc_zlog_debug_verbose("%s: entry, bi %p, rn %p", __func__, bi, rn); + vnc_zlog_debug_verbose("%s: entry, bpi %p, rn %p", __func__, bpi, rn); #endif new = XCALLOC(MTYPE_RFAPI_NEXTHOP, sizeof(struct rfapi_next_hop_entry)); @@ -1311,8 +1314,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, new->prefix = *rprefix; - if (bi->extra - && decode_rd_type(bi->extra->vnc.import.rd.val) + if (bpi->extra + && decode_rd_type(bpi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) { /* ethernet */ @@ -1327,19 +1330,19 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, memcpy(&vo->v.l2addr.macaddr, &rn->p.u.prefix_eth.octet, ETH_ALEN); /* only low 3 bytes of this are significant */ - if (bi->attr) { + if (bpi->attr) { (void)rfapiEcommunityGetLNI( - bi->attr->ecommunity, + bpi->attr->ecommunity, &vo->v.l2addr.logical_net_id); (void)rfapiEcommunityGetEthernetTag( - bi->attr->ecommunity, &vo->v.l2addr.tag_id); + bpi->attr->ecommunity, &vo->v.l2addr.tag_id); } /* local_nve_id comes from lower byte of RD type */ - vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; + vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1]; /* label comes from MP_REACH_NLRI label */ - vo->v.l2addr.label = decode_label(&bi->extra->label[0]); + vo->v.l2addr.label = decode_label(&bpi->extra->label[0]); new->vn_options = vo; @@ -1347,38 +1350,38 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, * If there is an auxiliary prefix (i.e., host IP address), * use it as the nexthop prefix instead of the query prefix */ - if (bi->extra->vnc.import.aux_prefix.family) { - rfapiQprefix2Rprefix(&bi->extra->vnc.import.aux_prefix, + if (bpi->extra->vnc.import.aux_prefix.family) { + rfapiQprefix2Rprefix(&bpi->extra->vnc.import.aux_prefix, &new->prefix); } } - if (bi->attr) { + if (bpi->attr) { bgp_encap_types tun_type; - new->prefix.cost = rfapiRfpCost(bi->attr); + new->prefix.cost = rfapiRfpCost(bpi->attr); struct bgp_attr_encap_subtlv *pEncap; - switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) { + switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) { case AF_INET: new->vn_address.addr_family = AF_INET; new->vn_address.addr.v4 = - bi->attr->mp_nexthop_global_in; + bpi->attr->mp_nexthop_global_in; break; case AF_INET6: new->vn_address.addr_family = AF_INET6; - new->vn_address.addr.v6 = bi->attr->mp_nexthop_global; + new->vn_address.addr.v6 = bpi->attr->mp_nexthop_global; break; default: zlog_warn("%s: invalid vpn nexthop length: %d", - __func__, bi->attr->mp_nexthop_len); + __func__, bpi->attr->mp_nexthop_len); rfapi_free_next_hop_list(new); return NULL; } - for (pEncap = bi->attr->vnc_subtlvs; pEncap; + for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { switch (pEncap->type) { case BGP_VNC_SUBTLV_TYPE_LIFETIME: @@ -1394,18 +1397,18 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, } } - rfapiGetTunnelType(bi->attr, &tun_type); + rfapiGetTunnelType(bpi->attr, &tun_type); if (tun_type == BGP_ENCAP_TYPE_MPLS) { struct prefix p; /* MPLS carries UN address in next hop */ - rfapiNexthop2Prefix(bi->attr, &p); + rfapiNexthop2Prefix(bpi->attr, &p); if (p.family != 0) { rfapiQprefix2Raddr(&p, &new->un_address); have_vnc_tunnel_un = 1; } } - for (pEncap = bi->attr->encap_subtlvs; pEncap; + for (pEncap = bpi->attr->encap_subtlvs; pEncap; pEncap = pEncap->next) { switch (pEncap->type) { case BGP_ENCAP_SUBTLV_TYPE_REMOTE_ENDPOINT: @@ -1430,8 +1433,8 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, default: zlog_warn( - "%s: invalid tunnel subtlv UN addr length (%d) for bi %p", - __func__, pEncap->length, bi); + "%s: invalid tunnel subtlv UN addr length (%d) for bpi %p", + __func__, pEncap->length, bpi); } break; @@ -1445,33 +1448,33 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, } } - new->un_options = rfapi_encap_tlv_to_un_option(bi->attr); + new->un_options = rfapi_encap_tlv_to_un_option(bpi->attr); #if DEBUG_ENCAP_MONITOR vnc_zlog_debug_verbose("%s: line %d: have_vnc_tunnel_un=%d", __func__, __LINE__, have_vnc_tunnel_un); #endif - if (!have_vnc_tunnel_un && bi->extra) { + if (!have_vnc_tunnel_un && bpi->extra) { /* * use cached UN address from ENCAP route */ new->un_address.addr_family = - bi->extra->vnc.import.un_family; + bpi->extra->vnc.import.un_family; switch (new->un_address.addr_family) { case AF_INET: new->un_address.addr.v4 = - bi->extra->vnc.import.un.addr4; + bpi->extra->vnc.import.un.addr4; break; case AF_INET6: new->un_address.addr.v6 = - bi->extra->vnc.import.un.addr6; + bpi->extra->vnc.import.un.addr6; break; default: zlog_warn( - "%s: invalid UN addr family (%d) for bi %p", + "%s: invalid UN addr family (%d) for bpi %p", __func__, new->un_address.addr_family, - bi); + bpi); rfapi_free_next_hop_list(new); return NULL; break; @@ -1485,13 +1488,13 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix, int rfapiHasNonRemovedRoutes(struct agg_node *rn) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { struct prefix pfx; - if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) - && (bi->extra && !rfapiGetUnAddrOfVpnBi(bi, &pfx))) { + if (!CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) + && (bpi->extra && !rfapiGetUnAddrOfVpnBi(bpi, &pfx))) { return 1; } @@ -1505,16 +1508,16 @@ int rfapiHasNonRemovedRoutes(struct agg_node *rn) */ void rfapiDumpNode(struct agg_node *rn) { - struct bgp_info *bi; + struct bgp_path_info *bpi; vnc_zlog_debug_verbose("%s: rn=%p", __func__, rn); - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { struct prefix pfx; - int ctrc = rfapiGetUnAddrOfVpnBi(bi, &pfx); + int ctrc = rfapiGetUnAddrOfVpnBi(bpi, &pfx); int nr; - if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) - && (bi->extra && !ctrc)) { + if (!CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) + && (bpi->extra && !ctrc)) { nr = 1; } else { @@ -1522,8 +1525,8 @@ void rfapiDumpNode(struct agg_node *rn) } vnc_zlog_debug_verbose( - " bi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d", bi, nr, - bi->flags, bi->extra, ctrc); + " bpi=%p, nr=%d, flags=0x%x, extra=%p, ctrc=%d", bpi, + nr, bpi->flags, bpi->extra, ctrc); } } #endif @@ -1539,7 +1542,7 @@ static int rfapiNhlAddNodeRoutes( struct agg_node *rfd_rib_node, /* preload this NVE rib node */ struct prefix *pfx_target_original) /* query target */ { - struct bgp_info *bi; + struct bgp_path_info *bpi; struct rfapi_next_hop_entry *new; struct prefix pfx_un; struct skiplist *seen_nexthops; @@ -1562,12 +1565,12 @@ static int rfapiNhlAddNodeRoutes( seen_nexthops = skiplist_new(0, vnc_prefix_cmp, (void (*)(void *))prefix_free); - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { struct prefix pfx_vn; struct prefix *newpfx; - if (removed && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (removed && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { #if DEBUG_RETURNED_NHL vnc_zlog_debug_verbose( "%s: want holddown, this route not holddown, skip", @@ -1575,18 +1578,18 @@ static int rfapiNhlAddNodeRoutes( #endif continue; } - if (!removed && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (!removed && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { continue; } - if (!bi->extra) { + if (!bpi->extra) { continue; } /* * Check for excluded VN address */ - if (rfapiVpnBiNhEqualsPt(bi, exclude_vnaddr)) + if (rfapiVpnBiNhEqualsPt(bpi, exclude_vnaddr)) continue; /* @@ -1595,9 +1598,9 @@ static int rfapiNhlAddNodeRoutes( if (is_l2) { /* L2 routes: semantic nexthop in aux_prefix; VN addr * ain't it */ - pfx_vn = bi->extra->vnc.import.aux_prefix; + pfx_vn = bpi->extra->vnc.import.aux_prefix; } else { - rfapiNexthop2Prefix(bi->attr, &pfx_vn); + rfapiNexthop2Prefix(bpi->attr, &pfx_vn); } if (!skiplist_search(seen_nexthops, &pfx_vn, NULL)) { #if DEBUG_RETURNED_NHL @@ -1611,10 +1614,10 @@ static int rfapiNhlAddNodeRoutes( continue; } - if (rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) { + if (rfapiGetUnAddrOfVpnBi(bpi, &pfx_un)) { #if DEBUG_ENCAP_MONITOR vnc_zlog_debug_verbose( - "%s: failed to get UN address of this VPN bi", + "%s: failed to get UN address of this VPN bpi", __func__); #endif continue; @@ -1624,10 +1627,10 @@ static int rfapiNhlAddNodeRoutes( *newpfx = pfx_vn; skiplist_insert(seen_nexthops, newpfx, newpfx); - new = rfapiRouteInfo2NextHopEntry(rprefix, bi, lifetime, rn); + new = rfapiRouteInfo2NextHopEntry(rprefix, bpi, lifetime, rn); if (new) { if (rfapiRibPreloadBi(rfd_rib_node, &pfx_vn, &pfx_un, - lifetime, bi)) { + lifetime, bpi)) { /* duplicate filtered by RIB */ rfapi_free_next_hop_list(new); new = NULL; @@ -1748,8 +1751,8 @@ static int rfapiNhlAddSubtree( * Construct an rfapi nexthop list based on the routes attached to * the specified node. * - * If there are any routes that do NOT have BGP_INFO_REMOVED set, - * return those only. If there are ONLY routes with BGP_INFO_REMOVED, + * If there are any routes that do NOT have BGP_PATH_REMOVED set, + * return those only. If there are ONLY routes with BGP_PATH_REMOVED, * then return those, and also include all the non-removed routes from the * next less-specific node (i.e., this node's parent) at the end. */ @@ -1991,16 +1994,16 @@ struct rfapi_next_hop_entry *rfapiEthRouteTable2NextHopList( } /* - * Insert a new bi to the imported route table node, - * keeping the list of BIs sorted best route first + * Insert a new bpi to the imported route table node, + * keeping the list of BPIs sorted best route first */ static void rfapiBgpInfoAttachSorted(struct agg_node *rn, - struct bgp_info *info_new, afi_t afi, + struct bgp_path_info *info_new, afi_t afi, safi_t safi) { struct bgp *bgp; - struct bgp_info *prev; - struct bgp_info *next; + struct bgp_path_info *prev; + struct bgp_path_info *next; char pfx_buf[PREFIX2STR_BUFFER]; @@ -2015,10 +2018,11 @@ static void rfapiBgpInfoAttachSorted(struct agg_node *rn, for (prev = NULL, next = rn->info; next; prev = next, next = next->next) { - if (!bgp || (!CHECK_FLAG(info_new->flags, BGP_INFO_REMOVED) - && CHECK_FLAG(next->flags, BGP_INFO_REMOVED)) - || bgp_info_cmp_compatible(bgp, info_new, next, pfx_buf, - afi, safi) + if (!bgp + || (!CHECK_FLAG(info_new->flags, BGP_PATH_REMOVED) + && CHECK_FLAG(next->flags, BGP_PATH_REMOVED)) + || bgp_path_info_cmp_compatible(bgp, info_new, next, + pfx_buf, afi, safi) == -1) { /* -1 if 1st is better */ break; } @@ -2036,18 +2040,18 @@ static void rfapiBgpInfoAttachSorted(struct agg_node *rn, bgp_attr_intern(info_new->attr); } -static void rfapiBgpInfoDetach(struct agg_node *rn, struct bgp_info *bi) +static void rfapiBgpInfoDetach(struct agg_node *rn, struct bgp_path_info *bpi) { /* * Remove the route (doubly-linked) */ - // bgp_attr_unintern (&bi->attr); - if (bi->next) - bi->next->prev = bi->prev; - if (bi->prev) - bi->prev->next = bi->next; + // bgp_attr_unintern (&bpi->attr); + if (bpi->next) + bpi->next->prev = bpi->prev; + if (bpi->prev) + bpi->prev->next = bpi->next; else - rn->info = bi->next; + rn->info = bpi->next; } /* @@ -2055,48 +2059,48 @@ static void rfapiBgpInfoDetach(struct agg_node *rn, struct bgp_info *bi) */ static int rfapi_bi_peer_rd_cmp(void *b1, void *b2) { - struct bgp_info *bi1 = b1; - struct bgp_info *bi2 = b2; + struct bgp_path_info *bpi1 = b1; + struct bgp_path_info *bpi2 = b2; /* * Compare peers */ - if (bi1->peer < bi2->peer) + if (bpi1->peer < bpi2->peer) return -1; - if (bi1->peer > bi2->peer) + if (bpi1->peer > bpi2->peer) return 1; /* * compare RDs */ - return vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd, - (struct prefix *)&bi2->extra->vnc.import.rd); + return vnc_prefix_cmp((struct prefix *)&bpi1->extra->vnc.import.rd, + (struct prefix *)&bpi2->extra->vnc.import.rd); } /* * For L2-indexed import tables - * The BIs in these tables should ALWAYS have an aux_prefix set because + * The BPIs in these tables should ALWAYS have an aux_prefix set because * they arrive via IPv4 or IPv6 advertisements. */ static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) { - struct bgp_info *bi1 = b1; - struct bgp_info *bi2 = b2; + struct bgp_path_info *bpi1 = b1; + struct bgp_path_info *bpi2 = b2; int rc; /* * Compare peers */ - if (bi1->peer < bi2->peer) + if (bpi1->peer < bpi2->peer) return -1; - if (bi1->peer > bi2->peer) + if (bpi1->peer > bpi2->peer) return 1; /* * compare RDs */ - rc = vnc_prefix_cmp((struct prefix *)&bi1->extra->vnc.import.rd, - (struct prefix *)&bi2->extra->vnc.import.rd); + rc = vnc_prefix_cmp((struct prefix *)&bpi1->extra->vnc.import.rd, + (struct prefix *)&bpi2->extra->vnc.import.rd); if (rc) { return rc; } @@ -2107,16 +2111,16 @@ static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) * * Use presence of aux_prefix with AF=ethernet and prefixlen=1 * as magic value to signify explicit wildcarding of the aux_prefix. - * This magic value will not appear in bona fide bi entries in - * the import table, but is allowed in the "fake" bi used to + * This magic value will not appear in bona fide bpi entries in + * the import table, but is allowed in the "fake" bpi used to * probe the table when searching. (We have to test both b1 and b2 * because there is no guarantee of the order the test key and * the real key will be passed) */ - if ((bi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET - && (bi1->extra->vnc.import.aux_prefix.prefixlen == 1)) - || (bi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET - && (bi2->extra->vnc.import.aux_prefix.prefixlen == 1))) { + if ((bpi1->extra->vnc.import.aux_prefix.family == AF_ETHERNET + && (bpi1->extra->vnc.import.aux_prefix.prefixlen == 1)) + || (bpi2->extra->vnc.import.aux_prefix.family == AF_ETHERNET + && (bpi2->extra->vnc.import.aux_prefix.prefixlen == 1))) { /* * wildcard aux address specified @@ -2124,8 +2128,8 @@ static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) return 0; } - return vnc_prefix_cmp(&bi1->extra->vnc.import.aux_prefix, - &bi2->extra->vnc.import.aux_prefix); + return vnc_prefix_cmp(&bpi1->extra->vnc.import.aux_prefix, + &bpi2->extra->vnc.import.aux_prefix); } @@ -2133,20 +2137,20 @@ static int rfapi_bi_peer_rd_aux_cmp(void *b1, void *b2) * Index on RD and Peer */ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* new BI */ + struct bgp_path_info *bpi) /* new BPI */ { struct skiplist *sl; assert(rn); - assert(bi); - assert(bi->extra); + assert(bpi); + assert(bpi->extra); { char buf[RD_ADDRSTRLEN]; - vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__, - bi, bi->peer, - prefix_rd2str(&bi->extra->vnc.import.rd, + vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__, + bpi, bpi->peer, + prefix_rd2str(&bpi->extra->vnc.import.rd, buf, sizeof(buf))); } @@ -2160,18 +2164,18 @@ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */ RFAPI_IT_EXTRA_GET(rn)->u.vpn.idx_rd = sl; agg_lock_node(rn); /* for skiplist */ } - assert(!skiplist_insert(sl, (void *)bi, (void *)bi)); + assert(!skiplist_insert(sl, (void *)bpi, (void *)bpi)); agg_lock_node(rn); /* for skiplist entry */ - /* NB: BIs in import tables are not refcounted */ + /* NB: BPIs in import tables are not refcounted */ } static void rfapiItBiIndexDump(struct agg_node *rn) { struct skiplist *sl; void *cursor = NULL; - struct bgp_info *k; - struct bgp_info *v; + struct bgp_path_info *k; + struct bgp_path_info *v; int rc; sl = RFAPI_RDINDEX(rn); @@ -2191,21 +2195,21 @@ static void rfapiItBiIndexDump(struct agg_node *rn) } else strncpy(buf_aux_pfx, "(none)", PREFIX_STRLEN); - vnc_zlog_debug_verbose("bi %p, peer %p, rd %s, aux_prefix %s", + vnc_zlog_debug_verbose("bpi %p, peer %p, rd %s, aux_prefix %s", k, k->peer, buf, buf_aux_pfx); } } -static struct bgp_info *rfapiItBiIndexSearch( +static struct bgp_path_info *rfapiItBiIndexSearch( struct agg_node *rn, /* Import table VPN node */ struct prefix_rd *prd, struct peer *peer, struct prefix *aux_prefix) /* optional L3 addr for L2 ITs */ { struct skiplist *sl; int rc; - struct bgp_info bi_fake; - struct bgp_info_extra bi_extra; - struct bgp_info *bi_result; + struct bgp_path_info bpi_fake; + struct bgp_path_info_extra bpi_extra; + struct bgp_path_info *bpi_result; sl = RFAPI_RDINDEX(rn); if (!sl) @@ -2236,22 +2240,22 @@ static struct bgp_info *rfapiItBiIndexSearch( vnc_zlog_debug_verbose("%s: short list algorithm", __func__); #endif /* if short list, linear search might be faster */ - for (bi_result = rn->info; bi_result; - bi_result = bi_result->next) { + for (bpi_result = rn->info; bpi_result; + bpi_result = bpi_result->next) { #if DEBUG_BI_SEARCH { char buf[RD_ADDRSTRLEN]; vnc_zlog_debug_verbose( - "%s: bi has prd=%s, peer=%p", __func__, - prefix_rd2str(&bi_result->extra->vnc + "%s: bpi has prd=%s, peer=%p", __func__, + prefix_rd2str(&bpi_result->extra->vnc .import.rd, buf, sizeof(buf)), - bi_result->peer); + bpi_result->peer); } #endif - if (peer == bi_result->peer - && !prefix_cmp((struct prefix *)&bi_result->extra + if (peer == bpi_result->peer + && !prefix_cmp((struct prefix *)&bpi_result->extra ->vnc.import.rd, (struct prefix *)prd)) { @@ -2261,9 +2265,10 @@ static struct bgp_info *rfapiItBiIndexSearch( __func__); #endif if (!aux_prefix - || !prefix_cmp(aux_prefix, - &bi_result->extra->vnc.import - .aux_prefix)) { + || !prefix_cmp( + aux_prefix, + &bpi_result->extra->vnc.import + .aux_prefix)) { #if DEBUG_BI_SEARCH vnc_zlog_debug_verbose("%s: match", @@ -2273,21 +2278,21 @@ static struct bgp_info *rfapiItBiIndexSearch( } } } - return bi_result; + return bpi_result; } - bi_fake.peer = peer; - bi_fake.extra = &bi_extra; - bi_fake.extra->vnc.import.rd = *(struct prefix_rd *)prd; + bpi_fake.peer = peer; + bpi_fake.extra = &bpi_extra; + bpi_fake.extra->vnc.import.rd = *(struct prefix_rd *)prd; if (aux_prefix) { - bi_fake.extra->vnc.import.aux_prefix = *aux_prefix; + bpi_fake.extra->vnc.import.aux_prefix = *aux_prefix; } else { /* wildcard */ - bi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET; - bi_fake.extra->vnc.import.aux_prefix.prefixlen = 1; + bpi_fake.extra->vnc.import.aux_prefix.family = AF_ETHERNET; + bpi_fake.extra->vnc.import.aux_prefix.prefixlen = 1; } - rc = skiplist_search(sl, (void *)&bi_fake, (void *)&bi_result); + rc = skiplist_search(sl, (void *)&bpi_fake, (void *)&bpi_result); if (rc) { #if DEBUG_BI_SEARCH @@ -2297,14 +2302,14 @@ static struct bgp_info *rfapiItBiIndexSearch( } #if DEBUG_BI_SEARCH - vnc_zlog_debug_verbose("%s: matched bi=%p", __func__, bi_result); + vnc_zlog_debug_verbose("%s: matched bpi=%p", __func__, bpi_result); #endif - return bi_result; + return bpi_result; } static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */ - struct bgp_info *bi) /* old BI */ + struct bgp_path_info *bpi) /* old BPI */ { struct skiplist *sl; int rc; @@ -2312,16 +2317,16 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */ { char buf[RD_ADDRSTRLEN]; - vnc_zlog_debug_verbose("%s: bi %p, peer %p, rd %s", __func__, - bi, bi->peer, - prefix_rd2str(&bi->extra->vnc.import.rd, + vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__, + bpi, bpi->peer, + prefix_rd2str(&bpi->extra->vnc.import.rd, buf, sizeof(buf))); } sl = RFAPI_RDINDEX(rn); assert(sl); - rc = skiplist_delete(sl, (void *)(bi), (void *)bi); + rc = skiplist_delete(sl, (void *)(bpi), (void *)bpi); if (rc) { rfapiItBiIndexDump(rn); } @@ -2329,17 +2334,18 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */ agg_unlock_node(rn); /* for skiplist entry */ - /* NB: BIs in import tables are not refcounted */ + /* NB: BPIs in import tables are not refcounted */ } /* * Add a backreference at the ENCAP node to the VPN route that * refers to it */ -static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, - struct prefix *p, /* VN address */ - struct agg_node *vpn_rn, /* VPN node */ - struct bgp_info *vpn_bi) /* VPN bi/route */ +static void +rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, + struct prefix *p, /* VN address */ + struct agg_node *vpn_rn, /* VPN node */ + struct bgp_path_info *vpn_bpi) /* VPN bpi/route */ { afi_t afi = family2afi(p->family); struct agg_node *rn; @@ -2354,7 +2360,7 @@ static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, assert(m); m->node = vpn_rn; - m->bi = vpn_bi; + m->bpi = vpn_bpi; m->rn = rn; /* insert to encap node's list */ @@ -2364,24 +2370,25 @@ static void rfapiMonitorEncapAdd(struct rfapi_import_table *import_table, RFAPI_MONITOR_ENCAP_W_ALLOC(rn) = m; /* for easy lookup when deleting vpn route */ - vpn_bi->extra->vnc.import.hme = m; + vpn_bpi->extra->vnc.import.hme = m; vnc_zlog_debug_verbose( - "%s: it=%p, vpn_bi=%p, afi=%d, encap rn=%p, setting vpn_bi->extra->vnc.import.hme=%p", - __func__, import_table, vpn_bi, afi, rn, m); + "%s: it=%p, vpn_bpi=%p, afi=%d, encap rn=%p, setting vpn_bpi->extra->vnc.import.hme=%p", + __func__, import_table, vpn_bpi, afi, rn, m); RFAPI_CHECK_REFCOUNT(rn, SAFI_ENCAP, 0); - bgp_attr_intern(vpn_bi->attr); + bgp_attr_intern(vpn_bpi->attr); } -static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi) +static void rfapiMonitorEncapDelete(struct bgp_path_info *vpn_bpi) { /* * Remove encap monitor */ - vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi); - if (vpn_bi->extra) { - struct rfapi_monitor_encap *hme = vpn_bi->extra->vnc.import.hme; + vnc_zlog_debug_verbose("%s: vpn_bpi=%p", __func__, vpn_bpi); + if (vpn_bpi->extra) { + struct rfapi_monitor_encap *hme = + vpn_bpi->extra->vnc.import.hme; if (hme) { @@ -2405,7 +2412,7 @@ static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi) agg_unlock_node(hme->rn); /* decr ref count */ XFREE(MTYPE_RFAPI_MONITOR_ENCAP, hme); - vpn_bi->extra->vnc.import.hme = NULL; + vpn_bpi->extra->vnc.import.hme = NULL; } } } @@ -2417,16 +2424,16 @@ static void rfapiMonitorEncapDelete(struct bgp_info *vpn_bi) static int rfapiWithdrawTimerVPN(struct thread *t) { struct rfapi_withdraw *wcb = t->arg; - struct bgp_info *bi = wcb->info; + struct bgp_path_info *bpi = wcb->info; struct bgp *bgp = bgp_get_default(); struct rfapi_monitor_vpn *moved; afi_t afi; assert(wcb->node); - assert(bi); + assert(bpi); assert(wcb->import_table); - assert(bi->extra); + assert(bpi->extra); RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_MPLS_VPN, wcb->lockoffset); @@ -2434,7 +2441,7 @@ static int rfapiWithdrawTimerVPN(struct thread *t) char buf[BUFSIZ]; vnc_zlog_debug_verbose( - "%s: removing bi %p at prefix %s/%d", __func__, bi, + "%s: removing bpi %p at prefix %s/%d", __func__, bpi, rfapi_ntop(wcb->node->p.family, &wcb->node->p.u.prefix, buf, BUFSIZ), wcb->node->p.prefixlen); @@ -2443,17 +2450,17 @@ static int rfapiWithdrawTimerVPN(struct thread *t) /* * Remove the route (doubly-linked) */ - if (CHECK_FLAG(bi->flags, BGP_INFO_VALID) - && VALID_INTERIOR_TYPE(bi->type)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_VALID) + && VALID_INTERIOR_TYPE(bpi->type)) RFAPI_MONITOR_EXTERIOR(wcb->node)->valid_interior_count--; afi = family2afi(wcb->node->p.family); wcb->import_table->holddown_count[afi] -= 1; /* keep count consistent */ - rfapiItBiIndexDel(wcb->node, bi); - rfapiBgpInfoDetach(wcb->node, bi); /* with removed bi */ + rfapiItBiIndexDel(wcb->node, bpi); + rfapiBgpInfoDetach(wcb->node, bpi); /* with removed bpi */ vnc_import_bgp_exterior_del_route_interior(bgp, wcb->import_table, - wcb->node, bi); + wcb->node, bpi); /* @@ -2465,7 +2472,7 @@ static int rfapiWithdrawTimerVPN(struct thread *t) & BGP_VNC_CONFIG_RESPONSE_REMOVAL_DISABLE)) { int has_valid_duplicate = 0; - struct bgp_info *bii; + struct bgp_path_info *bpii; /* * First check if there are any OTHER routes at this node @@ -2473,8 +2480,8 @@ static int rfapiWithdrawTimerVPN(struct thread *t) * there are (e.g., from other peers), then the route isn't * really gone, so skip sending a response removal message. */ - for (bii = wcb->node->info; bii; bii = bii->next) { - if (rfapiVpnBiSamePtUn(bi, bii)) { + for (bpii = wcb->node->info; bpii; bpii = bpii->next) { + if (rfapiVpnBiSamePtUn(bpi, bpii)) { has_valid_duplicate = 1; break; } @@ -2489,7 +2496,7 @@ static int rfapiWithdrawTimerVPN(struct thread *t) } } - rfapiMonitorEncapDelete(bi); + rfapiMonitorEncapDelete(bpi); /* * If there are no VPN monitors at this VPN Node A, @@ -2514,9 +2521,9 @@ static int rfapiWithdrawTimerVPN(struct thread *t) done: /* - * Free VPN bi + * Free VPN bpi */ - rfapiBgpInfoFree(bi); + rfapiBgpInfoFree(bpi); wcb->info = NULL; /* @@ -2613,48 +2620,48 @@ static int rfapiAttrNexthopAddrDifferent(struct prefix *p1, struct prefix *p2) return 1; } -static void rfapiCopyUnEncap2VPN(struct bgp_info *encap_bi, - struct bgp_info *vpn_bi) +static void rfapiCopyUnEncap2VPN(struct bgp_path_info *encap_bpi, + struct bgp_path_info *vpn_bpi) { - if (!encap_bi->attr) { - zlog_warn("%s: no encap bi attr/extra, can't copy UN address", + if (!encap_bpi->attr) { + zlog_warn("%s: no encap bpi attr/extra, can't copy UN address", __func__); return; } - if (!vpn_bi || !vpn_bi->extra) { - zlog_warn("%s: no vpn bi attr/extra, can't copy UN address", + if (!vpn_bpi || !vpn_bpi->extra) { + zlog_warn("%s: no vpn bpi attr/extra, can't copy UN address", __func__); return; } - switch (BGP_MP_NEXTHOP_FAMILY(encap_bi->attr->mp_nexthop_len)) { + switch (BGP_MP_NEXTHOP_FAMILY(encap_bpi->attr->mp_nexthop_len)) { case AF_INET: /* * instrumentation to debug segfault of 091127 */ - vnc_zlog_debug_verbose("%s: vpn_bi=%p", __func__, vpn_bi); - if (vpn_bi) { - vnc_zlog_debug_verbose("%s: vpn_bi->extra=%p", __func__, - vpn_bi->extra); + vnc_zlog_debug_verbose("%s: vpn_bpi=%p", __func__, vpn_bpi); + if (vpn_bpi) { + vnc_zlog_debug_verbose("%s: vpn_bpi->extra=%p", + __func__, vpn_bpi->extra); } - vpn_bi->extra->vnc.import.un_family = AF_INET; - vpn_bi->extra->vnc.import.un.addr4 = - encap_bi->attr->mp_nexthop_global_in; + vpn_bpi->extra->vnc.import.un_family = AF_INET; + vpn_bpi->extra->vnc.import.un.addr4 = + encap_bpi->attr->mp_nexthop_global_in; break; case AF_INET6: - vpn_bi->extra->vnc.import.un_family = AF_INET6; - vpn_bi->extra->vnc.import.un.addr6 = - encap_bi->attr->mp_nexthop_global; + vpn_bpi->extra->vnc.import.un_family = AF_INET6; + vpn_bpi->extra->vnc.import.un.addr6 = + encap_bpi->attr->mp_nexthop_global; break; default: zlog_warn("%s: invalid encap nexthop length: %d", __func__, - encap_bi->attr->mp_nexthop_len); - vpn_bi->extra->vnc.import.un_family = 0; + encap_bpi->attr->mp_nexthop_len); + vpn_bpi->extra->vnc.import.un_family = 0; break; } } @@ -2662,55 +2669,57 @@ static void rfapiCopyUnEncap2VPN(struct bgp_info *encap_bi, /* * returns 0 on success, nonzero on error */ -static int rfapiWithdrawEncapUpdateCachedUn( - struct rfapi_import_table *import_table, struct bgp_info *encap_bi, - struct agg_node *vpn_rn, struct bgp_info *vpn_bi) +static int +rfapiWithdrawEncapUpdateCachedUn(struct rfapi_import_table *import_table, + struct bgp_path_info *encap_bpi, + struct agg_node *vpn_rn, + struct bgp_path_info *vpn_bpi) { - if (!encap_bi) { + if (!encap_bpi) { /* * clear cached UN address */ - if (!vpn_bi || !vpn_bi->extra) { + if (!vpn_bpi || !vpn_bpi->extra) { zlog_warn( - "%s: missing VPN bi/extra, can't clear UN addr", + "%s: missing VPN bpi/extra, can't clear UN addr", __func__); return 1; } - vpn_bi->extra->vnc.import.un_family = 0; - memset(&vpn_bi->extra->vnc.import.un, 0, - sizeof(vpn_bi->extra->vnc.import.un)); - if (CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) { - if (rfapiGetVncTunnelUnAddr(vpn_bi->attr, NULL)) { - UNSET_FLAG(vpn_bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE(vpn_bi->type)) + vpn_bpi->extra->vnc.import.un_family = 0; + memset(&vpn_bpi->extra->vnc.import.un, 0, + sizeof(vpn_bpi->extra->vnc.import.un)); + if (CHECK_FLAG(vpn_bpi->flags, BGP_PATH_VALID)) { + if (rfapiGetVncTunnelUnAddr(vpn_bpi->attr, NULL)) { + UNSET_FLAG(vpn_bpi->flags, BGP_PATH_VALID); + if (VALID_INTERIOR_TYPE(vpn_bpi->type)) RFAPI_MONITOR_EXTERIOR(vpn_rn) ->valid_interior_count--; /* signal interior route withdrawal to * import-exterior */ vnc_import_bgp_exterior_del_route_interior( bgp_get_default(), import_table, vpn_rn, - vpn_bi); + vpn_bpi); } } } else { - if (!vpn_bi) { - zlog_warn("%s: missing VPN bi, can't clear UN addr", + if (!vpn_bpi) { + zlog_warn("%s: missing VPN bpi, can't clear UN addr", __func__); return 1; } - rfapiCopyUnEncap2VPN(encap_bi, vpn_bi); - if (!CHECK_FLAG(vpn_bi->flags, BGP_INFO_VALID)) { - SET_FLAG(vpn_bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE(vpn_bi->type)) + rfapiCopyUnEncap2VPN(encap_bpi, vpn_bpi); + if (!CHECK_FLAG(vpn_bpi->flags, BGP_PATH_VALID)) { + SET_FLAG(vpn_bpi->flags, BGP_PATH_VALID); + if (VALID_INTERIOR_TYPE(vpn_bpi->type)) RFAPI_MONITOR_EXTERIOR(vpn_rn) ->valid_interior_count++; /* signal interior route withdrawal to import-exterior */ vnc_import_bgp_exterior_add_route_interior( bgp_get_default(), import_table, vpn_rn, - vpn_bi); + vpn_bpi); } } return 0; @@ -2719,25 +2728,25 @@ static int rfapiWithdrawEncapUpdateCachedUn( static int rfapiWithdrawTimerEncap(struct thread *t) { struct rfapi_withdraw *wcb = t->arg; - struct bgp_info *bi = wcb->info; + struct bgp_path_info *bpi = wcb->info; int was_first_route = 0; struct rfapi_monitor_encap *em; struct skiplist *vpn_node_sl = skiplist_new(0, NULL, NULL); assert(wcb->node); - assert(bi); + assert(bpi); assert(wcb->import_table); RFAPI_CHECK_REFCOUNT(wcb->node, SAFI_ENCAP, 0); - if (wcb->node->info == bi) + if (wcb->node->info == bpi) was_first_route = 1; /* - * Remove the route/bi and free it + * Remove the route/bpi and free it */ - rfapiBgpInfoDetach(wcb->node, bi); - rfapiBgpInfoFree(bi); + rfapiBgpInfoDetach(wcb->node, bpi); + rfapiBgpInfoFree(bpi); if (!was_first_route) goto done; @@ -2745,13 +2754,13 @@ static int rfapiWithdrawTimerEncap(struct thread *t) for (em = RFAPI_MONITOR_ENCAP(wcb->node); em; em = em->next) { /* - * Update monitoring VPN BIs with new encap info at the - * head of the encap bi chain (which could be NULL after - * removing the expiring bi above) + * Update monitoring VPN BPIs with new encap info at the + * head of the encap bpi chain (which could be NULL after + * removing the expiring bpi above) */ if (rfapiWithdrawEncapUpdateCachedUn(wcb->import_table, wcb->node->info, em->node, - em->bi)) + em->bpi)) continue; /* @@ -2800,14 +2809,14 @@ done: */ static void rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, - struct agg_node *rn, struct bgp_info *bi, afi_t afi, - safi_t safi, + struct agg_node *rn, struct bgp_path_info *bpi, + afi_t afi, safi_t safi, int (*timer_service_func)(struct thread *)) { uint32_t lifetime; struct rfapi_withdraw *wcb; - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { /* * Already on the path to being withdrawn, * should already have a timer set up to @@ -2818,13 +2827,13 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, return; } - rfapiGetVncLifetime(bi->attr, &lifetime); + rfapiGetVncLifetime(bpi->attr, &lifetime); vnc_zlog_debug_verbose("%s: VNC lifetime is %u", __func__, lifetime); /* * withdrawn routes get to hang around for a while */ - SET_FLAG(bi->flags, BGP_INFO_REMOVED); + SET_FLAG(bpi->flags, BGP_PATH_REMOVED); /* set timer to remove the route later */ lifetime = rfapiGetHolddownFromLifetime(lifetime); @@ -2837,24 +2846,24 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); assert(wcb); wcb->node = rn; - wcb->info = bi; + wcb->info = bpi; wcb->import_table = import_table; - bgp_attr_intern(bi->attr); + bgp_attr_intern(bpi->attr); if (VNC_DEBUG(VERBOSE)) { vnc_zlog_debug_verbose( - "%s: wcb values: node=%p, info=%p, import_table=%p (bi follows)", + "%s: wcb values: node=%p, info=%p, import_table=%p (bpi follows)", __func__, wcb->node, wcb->info, wcb->import_table); - rfapiPrintBi(NULL, bi); + rfapiPrintBi(NULL, bpi); } - assert(bi->extra); + assert(bpi->extra); if (lifetime > UINT32_MAX / 1001) { /* sub-optimal case, but will probably never happen */ - bi->extra->vnc.import.timer = NULL; + bpi->extra->vnc.import.timer = NULL; thread_add_timer(bm->master, timer_service_func, wcb, lifetime, - &bi->extra->vnc.import.timer); + &bpi->extra->vnc.import.timer); } else { static uint32_t jitter; uint32_t lifetime_msec; @@ -2868,16 +2877,16 @@ rfapiBiStartWithdrawTimer(struct rfapi_import_table *import_table, lifetime_msec = (lifetime * 1000) + jitter; - bi->extra->vnc.import.timer = NULL; + bpi->extra->vnc.import.timer = NULL; thread_add_timer_msec(bm->master, timer_service_func, wcb, lifetime_msec, - &bi->extra->vnc.import.timer); + &bpi->extra->vnc.import.timer); } - /* re-sort route list (BGP_INFO_REMOVED routes are last) */ - if (((struct bgp_info *)rn->info)->next) { - rfapiBgpInfoDetach(rn, bi); - rfapiBgpInfoAttachSorted(rn, bi, afi, safi); + /* re-sort route list (BGP_PATH_REMOVED routes are last) */ + if (((struct bgp_path_info *)rn->info)->next) { + rfapiBgpInfoDetach(rn, bpi); + rfapiBgpInfoAttachSorted(rn, bpi, afi, safi); } } @@ -2890,7 +2899,7 @@ typedef void(rfapi_bi_filtered_import_f)(struct rfapi_import_table *, int, static void rfapiExpireEncapNow(struct rfapi_import_table *it, - struct agg_node *rn, struct bgp_info *bi) + struct agg_node *rn, struct bgp_path_info *bpi) { struct rfapi_withdraw *wcb; struct thread t; @@ -2899,7 +2908,7 @@ static void rfapiExpireEncapNow(struct rfapi_import_table *it, * pretend we're an expiring timer */ wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); - wcb->info = bi; + wcb->info = bpi; wcb->node = rn; wcb->import_table = it; memset(&t, 0, sizeof(t)); @@ -2929,7 +2938,7 @@ static int rfapiGetNexthop(struct attr *attr, struct prefix *prefix) } /* - * import a bgp_info if its route target list intersects with the + * import a bgp_path_info if its route target list intersects with the * import table's route target list */ static void rfapiBgpInfoFilteredImportEncap( @@ -2938,20 +2947,20 @@ static void rfapiBgpInfoFilteredImportEncap( struct prefix *p, struct prefix *aux_prefix, /* Unused for encap routes */ afi_t afi, struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - uint8_t type, /* part of bgp_info */ - uint8_t sub_type, /* part of bgp_info */ - uint32_t *label) /* part of bgp_info */ + struct attr *attr, /* part of bgp_path_info */ + uint8_t type, /* part of bgp_path_info */ + uint8_t sub_type, /* part of bgp_path_info */ + uint32_t *label) /* part of bgp_path_info */ { struct agg_table *rt = NULL; struct agg_node *rn; - struct bgp_info *info_new; - struct bgp_info *bi; - struct bgp_info *next; + struct bgp_path_info *info_new; + struct bgp_path_info *bpi; + struct bgp_path_info *next; char buf[BUFSIZ]; - struct prefix p_firstbi_old; - struct prefix p_firstbi_new; + struct prefix p_firstbpi_old; + struct prefix p_firstbpi_new; int replacing = 0; const char *action_str = NULL; struct prefix un_prefix; @@ -2978,8 +2987,8 @@ static void rfapiBgpInfoFilteredImportEncap( "%s: entry: %s: prefix %s/%d", __func__, action_str, inet_ntop(p->family, &p->u.prefix, buf, BUFSIZ), p->prefixlen); - memset(&p_firstbi_old, 0, sizeof(p_firstbi_old)); - memset(&p_firstbi_new, 0, sizeof(p_firstbi_new)); + memset(&p_firstbpi_old, 0, sizeof(p_firstbpi_old)); + memset(&p_firstbpi_new, 0, sizeof(p_firstbpi_new)); if (action == FIF_ACTION_UPDATE) { /* @@ -3055,37 +3064,37 @@ static void rfapiBgpInfoFilteredImportEncap( /* - * capture nexthop of first bi + * capture nexthop of first bpi */ if (rn->info) { rfapiNexthop2Prefix( - ((struct bgp_info *)(rn->info))->attr, - &p_firstbi_old); + ((struct bgp_path_info *)(rn->info))->attr, + &p_firstbpi_old); } - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { /* - * Does this bgp_info refer to the same route + * Does this bgp_path_info refer to the same route * as we are trying to add? */ - vnc_zlog_debug_verbose("%s: comparing BI %p", __func__, - bi); + vnc_zlog_debug_verbose("%s: comparing BPI %p", __func__, + bpi); /* * Compare RDs * - * RD of import table bi is in bi->extra->vnc.import.rd - * RD of info_orig is in prd + * RD of import table bpi is in + * bpi->extra->vnc.import.rd RD of info_orig is in prd */ - if (!bi->extra) { - vnc_zlog_debug_verbose("%s: no bi->extra", + if (!bpi->extra) { + vnc_zlog_debug_verbose("%s: no bpi->extra", __func__); continue; } if (prefix_cmp( - (struct prefix *)&bi->extra->vnc.import.rd, + (struct prefix *)&bpi->extra->vnc.import.rd, (struct prefix *)prd)) { vnc_zlog_debug_verbose("%s: prd does not match", @@ -3096,16 +3105,16 @@ static void rfapiBgpInfoFilteredImportEncap( /* * Compare peers */ - if (bi->peer != peer) { + if (bpi->peer != peer) { vnc_zlog_debug_verbose( "%s: peer does not match", __func__); continue; } - vnc_zlog_debug_verbose("%s: found matching bi", + vnc_zlog_debug_verbose("%s: found matching bpi", __func__); - /* Same route. Delete this bi, replace with new one */ + /* Same route. Delete this bpi, replace with new one */ if (action == FIF_ACTION_WITHDRAW) { @@ -3117,7 +3126,7 @@ static void rfapiBgpInfoFilteredImportEncap( rn->p.prefixlen); rfapiBiStartWithdrawTimer( - import_table, rn, bi, afi, SAFI_ENCAP, + import_table, rn, bpi, afi, SAFI_ENCAP, rfapiWithdrawTimerEncap); } else { @@ -3136,11 +3145,11 @@ static void rfapiBgpInfoFilteredImportEncap( * a previous withdraw, we must cancel its * timer. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) - && bi->extra->vnc.import.timer) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) + && bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi->extra->vnc + (struct thread *)bpi->extra->vnc .import.timer; struct rfapi_withdraw *wcb = t->arg; @@ -3149,13 +3158,13 @@ static void rfapiBgpInfoFilteredImportEncap( } if (action == FIF_ACTION_UPDATE) { - rfapiBgpInfoDetach(rn, bi); - rfapiBgpInfoFree(bi); + rfapiBgpInfoDetach(rn, bpi); + rfapiBgpInfoFree(bpi); replacing = 1; } else { /* * Kill: do export stuff when removing - * bi + * bpi */ struct rfapi_withdraw *wcb; struct thread t; @@ -3166,7 +3175,7 @@ static void rfapiBgpInfoFilteredImportEncap( wcb = XCALLOC( MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); - wcb->info = bi; + wcb->info = bpi; wcb->node = rn; wcb->import_table = import_table; memset(&t, 0, sizeof(t)); @@ -3191,7 +3200,7 @@ static void rfapiBgpInfoFilteredImportEncap( if (rn) { if (!replacing) - agg_lock_node(rn); /* incr ref count for new BI */ + agg_lock_node(rn); /* incr ref count for new BPI */ } else { rn = agg_node_get(rt, p); } @@ -3207,13 +3216,13 @@ static void rfapiBgpInfoFilteredImportEncap( * Delete holddown routes from same NVE. See details in * rfapiBgpInfoFilteredImportVPN() */ - for (bi = info_new->next; bi; bi = next) { + for (bpi = info_new->next; bpi; bpi = next) { struct prefix pfx_un; int un_match = 0; - next = bi->next; - if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + next = bpi->next; + if (!CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; /* @@ -3221,7 +3230,7 @@ static void rfapiBgpInfoFilteredImportEncap( * of the route node) */ - if (!rfapiGetNexthop(bi->attr, &pfx_un) + if (!rfapiGetNexthop(bpi->attr, &pfx_un) && prefix_same(&pfx_un, &un_prefix)) { un_match = 1; @@ -3231,21 +3240,21 @@ static void rfapiBgpInfoFilteredImportEncap( continue; vnc_zlog_debug_verbose( - "%s: removing holddown bi matching NVE of new route", + "%s: removing holddown bpi matching NVE of new route", __func__); - if (bi->extra->vnc.import.timer) { + if (bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi->extra->vnc.import.timer; + (struct thread *)bpi->extra->vnc.import.timer; struct rfapi_withdraw *wcb = t->arg; XFREE(MTYPE_RFAPI_WITHDRAW, wcb); thread_cancel(t); } - rfapiExpireEncapNow(import_table, rn, bi); + rfapiExpireEncapNow(import_table, rn, bpi); } - rfapiNexthop2Prefix(((struct bgp_info *)(rn->info))->attr, - &p_firstbi_new); + rfapiNexthop2Prefix(((struct bgp_path_info *)(rn->info))->attr, + &p_firstbpi_new); /* * If the nexthop address of the selected Encap route (i.e., @@ -3253,7 +3262,7 @@ static void rfapiBgpInfoFilteredImportEncap( * routes that refer to this Encap route and possibly force * rfapi callbacks. */ - if (rfapiAttrNexthopAddrDifferent(&p_firstbi_old, &p_firstbi_new)) { + if (rfapiAttrNexthopAddrDifferent(&p_firstbpi_old, &p_firstbpi_new)) { struct rfapi_monitor_encap *m; struct rfapi_monitor_encap *mnext; @@ -3284,19 +3293,19 @@ static void rfapiBgpInfoFilteredImportEncap( for (m = RFAPI_MONITOR_ENCAP(rn); m; m = m->next) { /* - * For each referenced bi/route, copy the ENCAP route's + * For each referenced bpi/route, copy the ENCAP route's * nexthop to the VPN route's cached UN address field * and set * the address family of the cached UN address field. */ - rfapiCopyUnEncap2VPN(info_new, m->bi); - if (!CHECK_FLAG(m->bi->flags, BGP_INFO_VALID)) { - SET_FLAG(m->bi->flags, BGP_INFO_VALID); - if (VALID_INTERIOR_TYPE(m->bi->type)) + rfapiCopyUnEncap2VPN(info_new, m->bpi); + if (!CHECK_FLAG(m->bpi->flags, BGP_PATH_VALID)) { + SET_FLAG(m->bpi->flags, BGP_PATH_VALID); + if (VALID_INTERIOR_TYPE(m->bpi->type)) RFAPI_MONITOR_EXTERIOR(m->node) ->valid_interior_count++; vnc_import_bgp_exterior_add_route_interior( - bgp, import_table, m->node, m->bi); + bgp, import_table, m->node, m->bpi); } /* @@ -3369,7 +3378,7 @@ static void rfapiBgpInfoFilteredImportEncap( } static void rfapiExpireVpnNow(struct rfapi_import_table *it, - struct agg_node *rn, struct bgp_info *bi, + struct agg_node *rn, struct bgp_path_info *bpi, int lockoffset) { struct rfapi_withdraw *wcb; @@ -3379,7 +3388,7 @@ static void rfapiExpireVpnNow(struct rfapi_import_table *it, * pretend we're an expiring timer */ wcb = XCALLOC(MTYPE_RFAPI_WITHDRAW, sizeof(struct rfapi_withdraw)); - wcb->info = bi; + wcb->info = bpi; wcb->node = rn; wcb->import_table = it; wcb->lockoffset = lockoffset; @@ -3390,7 +3399,7 @@ static void rfapiExpireVpnNow(struct rfapi_import_table *it, /* - * import a bgp_info if its route target list intersects with the + * import a bgp_path_info if its route target list intersects with the * import table's route target list */ void rfapiBgpInfoFilteredImportVPN( @@ -3399,17 +3408,17 @@ void rfapiBgpInfoFilteredImportVPN( struct prefix *p, struct prefix *aux_prefix, /* AFI_L2VPN: optional IP */ afi_t afi, struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - uint8_t type, /* part of bgp_info */ - uint8_t sub_type, /* part of bgp_info */ - uint32_t *label) /* part of bgp_info */ + struct attr *attr, /* part of bgp_path_info */ + uint8_t type, /* part of bgp_path_info */ + uint8_t sub_type, /* part of bgp_path_info */ + uint32_t *label) /* part of bgp_path_info */ { struct agg_table *rt = NULL; struct agg_node *rn; struct agg_node *n; - struct bgp_info *info_new; - struct bgp_info *bi; - struct bgp_info *next; + struct bgp_path_info *info_new; + struct bgp_path_info *bpi; + struct bgp_path_info *next; char buf[BUFSIZ]; struct prefix vn_prefix; struct prefix un_prefix; @@ -3524,25 +3533,25 @@ void rfapiBgpInfoFilteredImportVPN( /* * Look for same route (will have same RD and peer) */ - bi = rfapiItBiIndexSearch(rn, prd, peer, aux_prefix); + bpi = rfapiItBiIndexSearch(rn, prd, peer, aux_prefix); - if (bi) { + if (bpi) { /* * This was an old test when we iterated over the - * BIs linearly. Since we're now looking up with + * BPIs linearly. Since we're now looking up with * RD and peer, comparing types should not be * needed. Changed to assertion. * * Compare types. Doing so prevents a RFP-originated * route from matching an imported route, for example. */ - if (VNC_DEBUG(VERBOSE) && bi->type != type) + if (VNC_DEBUG(VERBOSE) && bpi->type != type) /* should be handled by RDs, but warn for now */ - zlog_warn("%s: type mismatch! (bi=%d, arg=%d)", - __func__, bi->type, type); + zlog_warn("%s: type mismatch! (bpi=%d, arg=%d)", + __func__, bpi->type, type); - vnc_zlog_debug_verbose("%s: found matching bi", + vnc_zlog_debug_verbose("%s: found matching bpi", __func__); /* @@ -3550,15 +3559,15 @@ void rfapiBgpInfoFilteredImportVPN( * holddown */ if (import_table == bgp->rfapi->it_ce) { - vnc_direct_bgp_del_route_ce(bgp, rn, bi); + vnc_direct_bgp_del_route_ce(bgp, rn, bpi); if (action == FIF_ACTION_WITHDRAW) action = FIF_ACTION_KILL; } if (action == FIF_ACTION_WITHDRAW) { - int washolddown = - CHECK_FLAG(bi->flags, BGP_INFO_REMOVED); + int washolddown = CHECK_FLAG(bpi->flags, + BGP_PATH_REMOVED); vnc_zlog_debug_verbose( "%s: withdrawing at prefix %s/%d%s", @@ -3573,12 +3582,12 @@ void rfapiBgpInfoFilteredImportVPN( VNC_ITRCCK; if (!washolddown) { rfapiBiStartWithdrawTimer( - import_table, rn, bi, afi, + import_table, rn, bpi, afi, SAFI_MPLS_VPN, rfapiWithdrawTimerVPN); RFAPI_UPDATE_ITABLE_COUNT( - bi, import_table, afi, -1); + bpi, import_table, afi, -1); import_table->holddown_count[afi] += 1; } VNC_ITRCCK; @@ -3599,11 +3608,11 @@ void rfapiBgpInfoFilteredImportVPN( * a previous withdraw, we must cancel its * timer. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) - && bi->extra->vnc.import.timer) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) + && bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi->extra->vnc + (struct thread *)bpi->extra->vnc .import.timer; struct rfapi_withdraw *wcb = t->arg; @@ -3612,15 +3621,15 @@ void rfapiBgpInfoFilteredImportVPN( import_table->holddown_count[afi] -= 1; RFAPI_UPDATE_ITABLE_COUNT( - bi, import_table, afi, 1); + bpi, import_table, afi, 1); } /* * decrement remote count (if route is remote) * because * we are going to remove it below */ - RFAPI_UPDATE_ITABLE_COUNT(bi, import_table, afi, - -1); + RFAPI_UPDATE_ITABLE_COUNT(bpi, import_table, + afi, -1); if (action == FIF_ACTION_UPDATE) { replacing = 1; @@ -3628,31 +3637,31 @@ void rfapiBgpInfoFilteredImportVPN( * make copy of original nexthop so we * can see if it changed */ - rfapiGetNexthop(bi->attr, + rfapiGetNexthop(bpi->attr, &original_nexthop); /* - * remove bi without doing any export + * remove bpi without doing any export * processing */ - if (CHECK_FLAG(bi->flags, - BGP_INFO_VALID) - && VALID_INTERIOR_TYPE(bi->type)) + if (CHECK_FLAG(bpi->flags, + BGP_PATH_VALID) + && VALID_INTERIOR_TYPE(bpi->type)) RFAPI_MONITOR_EXTERIOR(rn) ->valid_interior_count--; - rfapiItBiIndexDel(rn, bi); - rfapiBgpInfoDetach(rn, bi); - rfapiMonitorEncapDelete(bi); + rfapiItBiIndexDel(rn, bpi); + rfapiBgpInfoDetach(rn, bpi); + rfapiMonitorEncapDelete(bpi); vnc_import_bgp_exterior_del_route_interior( - bgp, import_table, rn, bi); - rfapiBgpInfoFree(bi); + bgp, import_table, rn, bpi); + rfapiBgpInfoFree(bpi); } else { /* Kill */ /* - * remove bi and do export processing + * remove bpi and do export processing */ import_table->holddown_count[afi] += 1; - rfapiExpireVpnNow(import_table, rn, bi, + rfapiExpireVpnNow(import_table, rn, bpi, 0); } } @@ -3700,16 +3709,17 @@ void rfapiBgpInfoFilteredImportVPN( /* * For ethernet routes, if there is an accompanying IP address, - * save it in the bi + * save it in the bpi */ if ((AFI_L2VPN == afi) && aux_prefix) { - vnc_zlog_debug_verbose("%s: setting BI's aux_prefix", __func__); + vnc_zlog_debug_verbose("%s: setting BPI's aux_prefix", + __func__); info_new->extra->vnc.import.aux_prefix = *aux_prefix; } vnc_zlog_debug_verbose( - "%s: inserting bi %p at prefix %s/%d #%d", __func__, info_new, + "%s: inserting bpi %p at prefix %s/%d #%d", __func__, info_new, rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), rn->p.prefixlen, rn->lock); @@ -3718,7 +3728,7 @@ void rfapiBgpInfoFilteredImportVPN( if (!rfapiGetUnAddrOfVpnBi(info_new, NULL)) { if (VALID_INTERIOR_TYPE(info_new->type)) RFAPI_MONITOR_EXTERIOR(rn)->valid_interior_count++; - SET_FLAG(info_new->flags, BGP_INFO_VALID); + SET_FLAG(info_new->flags, BGP_PATH_VALID); } RFAPI_UPDATE_ITABLE_COUNT(info_new, import_table, afi, 1); vnc_import_bgp_exterior_add_route_interior(bgp, import_table, rn, @@ -3779,40 +3789,40 @@ void rfapiBgpInfoFilteredImportVPN( * by the fresh route). */ /* - * We know that the new bi will have been inserted before any routes + * We know that the new bpi will have been inserted before any routes * in holddown, so we can skip any that came before it */ - for (bi = info_new->next; bi; bi = next) { + for (bpi = info_new->next; bpi; bpi = next) { struct prefix pfx_vn; struct prefix pfx_un; int un_match = 0; int remote_peer_match = 0; - next = bi->next; + next = bpi->next; /* * Must be holddown */ - if (!CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (!CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; /* * Must match VN address (nexthop of VPN route) */ - if (rfapiGetNexthop(bi->attr, &pfx_vn)) + if (rfapiGetNexthop(bpi->attr, &pfx_vn)) continue; if (!prefix_same(&pfx_vn, &vn_prefix)) continue; if (un_prefix_valid && /* new route UN addr */ - !rfapiGetUnAddrOfVpnBi(bi, &pfx_un) + !rfapiGetUnAddrOfVpnBi(bpi, &pfx_un) && /* old route UN addr */ prefix_same(&pfx_un, &un_prefix)) { /* compare */ un_match = 1; } - if (!RFAPI_LOCAL_BI(bi) && !RFAPI_LOCAL_BI(info_new) - && sockunion_same(&bi->peer->su, &info_new->peer->su)) { + if (!RFAPI_LOCAL_BI(bpi) && !RFAPI_LOCAL_BI(info_new) + && sockunion_same(&bpi->peer->su, &info_new->peer->su)) { /* old & new are both remote, same peer */ remote_peer_match = 1; } @@ -3821,17 +3831,17 @@ void rfapiBgpInfoFilteredImportVPN( continue; vnc_zlog_debug_verbose( - "%s: removing holddown bi matching NVE of new route", + "%s: removing holddown bpi matching NVE of new route", __func__); - if (bi->extra->vnc.import.timer) { + if (bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi->extra->vnc.import.timer; + (struct thread *)bpi->extra->vnc.import.timer; struct rfapi_withdraw *wcb = t->arg; XFREE(MTYPE_RFAPI_WITHDRAW, wcb); thread_cancel(t); } - rfapiExpireVpnNow(import_table, rn, bi, 0); + rfapiExpireVpnNow(import_table, rn, bpi, 0); } if (!original_had_routes) { @@ -3877,10 +3887,10 @@ static void rfapiBgpInfoFilteredImportBadSafi( struct prefix *p, struct prefix *aux_prefix, /* AFI_L2VPN: optional IP */ afi_t afi, struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - uint8_t type, /* part of bgp_info */ - uint8_t sub_type, /* part of bgp_info */ - uint32_t *label) /* part of bgp_info */ + struct attr *attr, /* part of bgp_path_info */ + uint8_t type, /* part of bgp_path_info */ + uint8_t sub_type, /* part of bgp_path_info */ + uint32_t *label) /* part of bgp_path_info */ { vnc_zlog_debug_verbose("%s: Error, bad safi", __func__); } @@ -4088,22 +4098,22 @@ void rfapiProcessWithdraw(struct peer *peer, void *rfd, struct prefix *p, * routes expiring at the same time due to peer drop. */ /* - * 1. Visit all BIs in all ENCAP import tables. + * 1. Visit all BPIs in all ENCAP import tables. * - * a. If a bi's peer is the failed peer, remove the bi. - * b. If the removed ENCAP bi was first in the list of - * BIs at this ENCAP node, loop over all monitors + * a. If a bpi's peer is the failed peer, remove the bpi. + * b. If the removed ENCAP bpi was first in the list of + * BPIs at this ENCAP node, loop over all monitors * at this node: * * (1) for each ENCAP monitor, loop over all its * VPN node monitors and set their RFAPI_MON_FLAG_NEEDCALLBACK * flags. * - * 2. Visit all BIs in all VPN import tables. - * a. If a bi's peer is the failed peer, remove the bi. + * 2. Visit all BPIs in all VPN import tables. + * a. If a bpi's peer is the failed peer, remove the bpi. * b. loop over all the VPN node monitors and set their * RFAPI_MON_FLAG_NEEDCALLBACK flags - * c. If there are no BIs left at this VPN node, + * c. If there are no BPIs left at this VPN node, * */ @@ -4114,7 +4124,7 @@ static void rfapiProcessPeerDownRt(struct peer *peer, afi_t afi, safi_t safi) { struct agg_node *rn; - struct bgp_info *bi; + struct bgp_path_info *bpi; struct agg_table *rt; int (*timer_service_func)(struct thread *); @@ -4137,20 +4147,20 @@ static void rfapiProcessPeerDownRt(struct peer *peer, for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { - for (bi = rn->info; bi; bi = bi->next) { - if (bi->peer == peer) { + for (bpi = rn->info; bpi; bpi = bpi->next) { + if (bpi->peer == peer) { - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { /* already in holddown, skip */ continue; } if (safi == SAFI_MPLS_VPN) { RFAPI_UPDATE_ITABLE_COUNT( - bi, import_table, afi, -1); + bpi, import_table, afi, -1); import_table->holddown_count[afi] += 1; } - rfapiBiStartWithdrawTimer(import_table, rn, bi, + rfapiBiStartWithdrawTimer(import_table, rn, bpi, afi, safi, timer_service_func); } @@ -4182,11 +4192,11 @@ void rfapiProcessPeerDown(struct peer *peer) return; /* - * 1. Visit all BIs in all ENCAP import tables. - * Start withdraw timer on the BIs that match peer. + * 1. Visit all BPIs in all ENCAP import tables. + * Start withdraw timer on the BPIs that match peer. * - * 2. Visit All BIs in all VPN import tables. - * Start withdraw timer on the BIs that match peer. + * 2. Visit All BPIs in all VPN import tables. + * Start withdraw timer on the BPIs that match peer. */ bgp = bgp_get_default(); /* assume 1 instance for now */ @@ -4238,27 +4248,27 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp, for (rn2 = bgp_table_top(rn1->info); rn2; rn2 = bgp_route_next(rn2)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn2->info; bi; bi = bi->next) { + for (bpi = rn2->info; bpi; bpi = bpi->next) { uint32_t label = 0; - if (CHECK_FLAG(bi->flags, - BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, + BGP_PATH_REMOVED)) continue; - if (bi->extra) + if (bpi->extra) label = decode_label( - &bi->extra->label[0]); + &bpi->extra->label[0]); (*rfapiBgpInfoFilteredImportFunction( safi))( it, /* which import table */ - FIF_ACTION_UPDATE, bi->peer, + FIF_ACTION_UPDATE, bpi->peer, NULL, &rn2->p, /* prefix */ NULL, afi, (struct prefix_rd *)&rn1->p, - bi->attr, bi->type, - bi->sub_type, &label); + bpi->attr, bpi->type, + bpi->sub_type, &label); } } } @@ -4472,10 +4482,10 @@ static void rfapiDeleteRemotePrefixesIt( afi); for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { - struct bgp_info *bi; - struct bgp_info *next; + 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]; @@ -4499,8 +4509,8 @@ static void rfapiDeleteRemotePrefixesIt( /* TBD is this valid for afi == AFI_L2VPN? */ RFAPI_CHECK_REFCOUNT(rn, SAFI_MPLS_VPN, 1); - for (bi = rn->info; bi; bi = next) { - next = bi->next; + for (bpi = rn->info; bpi; bpi = next) { + next = bpi->next; struct prefix qpt; struct prefix qct; @@ -4508,11 +4518,11 @@ static void rfapiDeleteRemotePrefixesIt( int qct_valid = 0; int is_active = 0; - vnc_zlog_debug_verbose("%s: examining bi %p", - __func__, bi); + vnc_zlog_debug_verbose("%s: examining bpi %p", + __func__, bpi); - if (bi->attr) { - if (!rfapiGetNexthop(bi->attr, &qpt)) + if (bpi->attr) { + if (!rfapiGetNexthop(bpi->attr, &qpt)) qpt_valid = 1; } if (vn) { @@ -4527,7 +4537,7 @@ static void rfapiDeleteRemotePrefixesIt( } } - if (!rfapiGetUnAddrOfVpnBi(bi, &qct)) + if (!rfapiGetUnAddrOfVpnBi(bpi, &qct)) qct_valid = 1; if (un) { @@ -4544,7 +4554,7 @@ static void rfapiDeleteRemotePrefixesIt( /* - * Blow bi away + * Blow bpi away */ /* * If this route is waiting to be deleted @@ -4552,13 +4562,13 @@ static void rfapiDeleteRemotePrefixesIt( * a previous withdraw, we must cancel its * timer. */ - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { if (!delete_holddown) continue; - if (bi->extra->vnc.import.timer) { + if (bpi->extra->vnc.import.timer) { struct thread *t = - (struct thread *)bi + (struct thread *)bpi ->extra->vnc .import.timer; struct rfapi_withdraw *wcb = @@ -4568,7 +4578,7 @@ static void rfapiDeleteRemotePrefixesIt( ->holddown_count[afi] -= 1; RFAPI_UPDATE_ITABLE_COUNT( - bi, wcb->import_table, + bpi, wcb->import_table, afi, 1); XFREE(MTYPE_RFAPI_WITHDRAW, wcb); @@ -4581,8 +4591,8 @@ static void rfapiDeleteRemotePrefixesIt( } vnc_zlog_debug_verbose( - "%s: deleting bi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)", - __func__, bi, qct_valid, qpt_valid, + "%s: deleting bpi %p (qct_valid=%d, qpt_valid=%d, delete_holddown=%d, delete_active=%d)", + __func__, bpi, qct_valid, qpt_valid, delete_holddown, delete_active); @@ -4628,11 +4638,11 @@ static void rfapiDeleteRemotePrefixesIt( } vnc_direct_bgp_rh_del_route(bgp, afi, &rn->p, - bi->peer); + bpi->peer); - RFAPI_UPDATE_ITABLE_COUNT(bi, it, afi, -1); + RFAPI_UPDATE_ITABLE_COUNT(bpi, it, afi, -1); it->holddown_count[afi] += 1; - rfapiExpireVpnNow(it, rn, bi, 1); + rfapiExpireVpnNow(it, rn, bpi, 1); vnc_zlog_debug_verbose( "%s: incrementing count (is_active=%d)", diff --git a/bgpd/rfapi/rfapi_import.h b/bgpd/rfapi/rfapi_import.h index ae3d248367..1ab9cc5193 100644 --- a/bgpd/rfapi/rfapi_import.h +++ b/bgpd/rfapi/rfapi_import.h @@ -31,7 +31,7 @@ /* * These are per-rt-import-list * - * routes are not segregated by RD - the RD is stored in bgp_info_extra + * routes are not segregated by RD - the RD is stored in bgp_path_info_extra * and is needed to determine if two prefixes are the same. */ struct rfapi_import_table { @@ -51,18 +51,18 @@ struct rfapi_import_table { int imported_count[AFI_MAX]; }; -#define RFAPI_LOCAL_BI(bi) \ - (((bi)->type == ZEBRA_ROUTE_BGP) && ((bi)->sub_type == BGP_ROUTE_RFP)) +#define RFAPI_LOCAL_BI(bpi) \ + (((bpi)->type == ZEBRA_ROUTE_BGP) && ((bpi)->sub_type == BGP_ROUTE_RFP)) -#define RFAPI_DIRECT_IMPORT_BI(bi) \ - (((bi)->type == ZEBRA_ROUTE_BGP_DIRECT) \ - || ((bi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)) +#define RFAPI_DIRECT_IMPORT_BI(bpi) \ + (((bpi)->type == ZEBRA_ROUTE_BGP_DIRECT) \ + || ((bpi)->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)) -#define RFAPI_UPDATE_ITABLE_COUNT(bi, itable, afi, cnt) \ - if (RFAPI_LOCAL_BI(bi)) { \ +#define RFAPI_UPDATE_ITABLE_COUNT(bpi, itable, afi, cnt) \ + if (RFAPI_LOCAL_BI(bpi)) { \ (itable)->local_count[(afi)] += (cnt); \ } else { \ - if (RFAPI_DIRECT_IMPORT_BI(bi)) \ + if (RFAPI_DIRECT_IMPORT_BI(bpi)) \ (itable)->imported_count[(afi)] += (cnt); \ else \ (itable)->remote_count[(afi)] += (cnt); \ @@ -75,9 +75,9 @@ extern void rfapiDebugBacktrace(void); extern void rfapiCheckRouteCount(void); /* - * Print BI in an Import Table + * Print BPI in an Import Table */ -extern void rfapiPrintBi(void *stream, struct bgp_info *bi); +extern void rfapiPrintBi(void *stream, struct bgp_path_info *bpi); extern void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt, int isvpn); @@ -94,7 +94,7 @@ extern void rfapiImportTableRefDelByIt(struct bgp *bgp, * Construct an rfapi nexthop list based on the routes attached to * the specified node. * - * If there are any routes that do NOT have BGP_INFO_REMOVED set, + * If there are any routes that do NOT have BGP_PATH_REMOVED set, * return those only. If there are ONLY routes with BGP_INFO_REMOVED, * then return those, and also include all the non-removed routes from the * next less-specific node (i.e., this node's parent) at the end. @@ -128,7 +128,7 @@ extern int rfapiHasNonRemovedRoutes(struct agg_node *rn); extern int rfapiProcessDeferredClose(struct thread *t); -extern int rfapiGetUnAddrOfVpnBi(struct bgp_info *bi, struct prefix *p); +extern int rfapiGetUnAddrOfVpnBi(struct bgp_path_info *bpi, struct prefix *p); extern void rfapiNexthop2Prefix(struct attr *attr, struct prefix *p); @@ -146,10 +146,10 @@ extern void rfapiBgpInfoFilteredImportVPN( struct prefix *p, struct prefix *aux_prefix, /* AFI_ETHER: optional IP */ afi_t afi, struct prefix_rd *prd, - struct attr *attr, /* part of bgp_info */ - uint8_t type, /* part of bgp_info */ - uint8_t sub_type, /* part of bgp_info */ - uint32_t *label); /* part of bgp_info */ + struct attr *attr, /* part of bgp_path_info */ + uint8_t type, /* part of bgp_path_info */ + uint8_t sub_type, /* part of bgp_path_info */ + uint32_t *label); /* part of bgp_path_info */ extern struct rfapi_next_hop_entry *rfapiEthRouteNode2NextHopList( struct agg_node *rn, struct rfapi_ip_prefix *rprefix, diff --git a/bgpd/rfapi/rfapi_monitor.c b/bgpd/rfapi/rfapi_monitor.c index f18c6bfe12..dc1f7e0fbb 100644 --- a/bgpd/rfapi/rfapi_monitor.c +++ b/bgpd/rfapi/rfapi_monitor.c @@ -226,7 +226,7 @@ void rfapiMonitorExtraFlush(safi_t safi, struct agg_node *rn) agg_unlock_node(rn); } if (hie->u.vpn.idx_rd) { - /* looping through bi->extra->vnc.import.rd is tbd */ + /* looping through bpi->extra->vnc.import.rd is tbd */ while (!skiplist_delete_first(hie->u.vpn.idx_rd)) { agg_unlock_node(rn); } @@ -346,16 +346,16 @@ struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, for (rn = agg_node_match(rfd->import_table->imported_vpn[afi], p); rn;) { - struct bgp_info *bi; + struct bgp_path_info *bpi; struct prefix pfx_dummy; /* TBD update this code to use new valid_interior_count */ - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { /* * If there is a cached ENCAP UN address, it's a usable * VPN route */ - if (bi->extra && bi->extra->vnc.import.un_family) { + if (bpi->extra && bpi->extra->vnc.import.un_family) { break; } @@ -364,11 +364,11 @@ struct agg_node *rfapiMonitorGetAttachNode(struct rfapi_descriptor *rfd, * address, * it's a usable VPN route. */ - if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_dummy)) { + if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_dummy)) { break; } } - if (bi) + if (bpi) break; agg_unlock_node(rn); diff --git a/bgpd/rfapi/rfapi_monitor.h b/bgpd/rfapi/rfapi_monitor.h index 9b85f6248e..b8eec56475 100644 --- a/bgpd/rfapi/rfapi_monitor.h +++ b/bgpd/rfapi/rfapi_monitor.h @@ -45,7 +45,7 @@ struct rfapi_monitor_encap { struct rfapi_monitor_encap *next; struct rfapi_monitor_encap *prev; struct agg_node *node; /* VPN node */ - struct bgp_info *bi; /* VPN bi */ + struct bgp_path_info *bpi; /* VPN bpi */ struct agg_node *rn; /* parent node */ }; @@ -83,7 +83,7 @@ struct rfapi_it_extra { * Encap TLV */ int valid_interior_count; - /* unicast exterior routes, key=bi, + /* unicast exterior routes, key=bpi, * val=allocated prefix */ struct skiplist *source; } e; diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h index 4d8072a49b..87d9a32f67 100644 --- a/bgpd/rfapi/rfapi_private.h +++ b/bgpd/rfapi/rfapi_private.h @@ -212,7 +212,7 @@ struct rfapi { /* * when importing bgp-direct routes in resolve-nve mode, - * this list maps unicast route nexthops to their bgp_infos + * this list maps unicast route nexthops to their bgp_path_infos * in the unicast table */ struct skiplist *resolve_nve_nexthop; diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c index fa8c038d6f..520cc141c0 100644 --- a/bgpd/rfapi/rfapi_rib.c +++ b/bgpd/rfapi/rfapi_rib.c @@ -616,18 +616,18 @@ void rfapiRibFree(struct rfapi_descriptor *rfd) } /* - * Copies struct bgp_info to struct rfapi_info, except for rk fields and un + * Copies struct bgp_path_info to struct rfapi_info, except for rk fields and un */ -static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, +static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri, uint32_t lifetime) { struct bgp_attr_encap_subtlv *pEncap; - ri->cost = rfapiRfpCost(bi->attr); + ri->cost = rfapiRfpCost(bpi->attr); ri->lifetime = lifetime; /* This loop based on rfapiRouteInfo2NextHopEntry() */ - for (pEncap = bi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { + for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { struct bgp_tea_options *hop; switch (pEncap->type) { @@ -665,13 +665,13 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, } rfapi_un_options_free(ri->un_options); /* maybe free old version */ - ri->un_options = rfapi_encap_tlv_to_un_option(bi->attr); + ri->un_options = rfapi_encap_tlv_to_un_option(bpi->attr); /* * VN options */ - if (bi->extra - && decode_rd_type(bi->extra->vnc.import.rd.val) + if (bpi->extra + && decode_rd_type(bpi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) { /* ethernet route */ @@ -683,21 +683,21 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, vo->type = RFAPI_VN_OPTION_TYPE_L2ADDR; - /* copy from RD already stored in bi, so we don't need it_node + /* copy from RD already stored in bpi, so we don't need it_node */ - memcpy(&vo->v.l2addr.macaddr, bi->extra->vnc.import.rd.val + 2, + memcpy(&vo->v.l2addr.macaddr, bpi->extra->vnc.import.rd.val + 2, ETH_ALEN); - (void)rfapiEcommunityGetLNI(bi->attr->ecommunity, + (void)rfapiEcommunityGetLNI(bpi->attr->ecommunity, &vo->v.l2addr.logical_net_id); - (void)rfapiEcommunityGetEthernetTag(bi->attr->ecommunity, + (void)rfapiEcommunityGetEthernetTag(bpi->attr->ecommunity, &vo->v.l2addr.tag_id); /* local_nve_id comes from RD */ - vo->v.l2addr.local_nve_id = bi->extra->vnc.import.rd.val[1]; + vo->v.l2addr.local_nve_id = bpi->extra->vnc.import.rd.val[1]; /* label comes from MP_REACH_NLRI label */ - vo->v.l2addr.label = decode_label(&bi->extra->label[0]); + vo->v.l2addr.label = decode_label(&bpi->extra->label[0]); rfapi_vn_options_free( ri->vn_options); /* maybe free old version */ @@ -707,8 +707,8 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, /* * If there is an auxiliary IP address (L2 can have it), copy it */ - if (bi->extra && bi->extra->vnc.import.aux_prefix.family) { - ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) { + ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix; } } @@ -733,7 +733,7 @@ static void rfapiRibBi2Ri(struct bgp_info *bi, struct rfapi_info *ri, int rfapiRibPreloadBi( struct agg_node *rfd_rib_node, /* NULL = don't preload or filter */ struct prefix *pfx_vn, struct prefix *pfx_un, uint32_t lifetime, - struct bgp_info *bi) + struct bgp_path_info *bpi) { struct rfapi_descriptor *rfd; struct skiplist *slRibPt = NULL; @@ -751,13 +751,13 @@ int rfapiRibPreloadBi( memset((void *)&rk, 0, sizeof(rk)); rk.vn = *pfx_vn; - rk.rd = bi->extra->vnc.import.rd; + rk.rd = bpi->extra->vnc.import.rd; /* * If there is an auxiliary IP address (L2 can have it), copy it */ - if (bi->extra->vnc.import.aux_prefix.family) { - rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + if (bpi->extra->vnc.import.aux_prefix.family) { + rk.aux_prefix = bpi->extra->vnc.import.aux_prefix; } /* @@ -774,13 +774,13 @@ int rfapiRibPreloadBi( /* found: update contents of existing route in RIB */ ori->un = *pfx_un; - rfapiRibBi2Ri(bi, ori, lifetime); + rfapiRibBi2Ri(bpi, ori, lifetime); } else { /* not found: add new route to RIB */ ori = rfapi_info_new(); ori->rk = rk; ori->un = *pfx_un; - rfapiRibBi2Ri(bi, ori, lifetime); + rfapiRibBi2Ri(bpi, ori, lifetime); if (!slRibPt) { slRibPt = skiplist_new(0, rfapi_rib_key_cmp, NULL); @@ -1590,7 +1590,7 @@ void rfapiRibUpdatePendingNode( struct agg_node *it_node, uint32_t lifetime) { struct prefix *prefix; - struct bgp_info *bi; + struct bgp_path_info *bpi; struct agg_node *pn; afi_t afi; uint32_t queued_flag; @@ -1640,25 +1640,25 @@ void rfapiRibUpdatePendingNode( } /* - * The BIs in the import table are already sorted by cost + * The BPIs in the import table are already sorted by cost */ - for (bi = it_node->info; bi; bi = bi->next) { + for (bpi = it_node->info; bpi; bpi = bpi->next) { struct rfapi_info *ri; struct prefix pfx_nh; - if (!bi->attr) { + if (!bpi->attr) { /* shouldn't happen */ /* TBD increment error stats counter */ continue; } - if (!bi->extra) { + if (!bpi->extra) { /* shouldn't happen */ /* TBD increment error stats counter */ continue; } - rfapiNexthop2Prefix(bi->attr, &pfx_nh); + rfapiNexthop2Prefix(bpi->attr, &pfx_nh); /* * Omit route if nexthop is self @@ -1675,15 +1675,15 @@ void rfapiRibUpdatePendingNode( ri = rfapi_info_new(); ri->rk.vn = pfx_nh; - ri->rk.rd = bi->extra->vnc.import.rd; + ri->rk.rd = bpi->extra->vnc.import.rd; /* * If there is an auxiliary IP address (L2 can have it), copy it */ - if (bi->extra->vnc.import.aux_prefix.family) { - ri->rk.aux_prefix = bi->extra->vnc.import.aux_prefix; + if (bpi->extra->vnc.import.aux_prefix.family) { + ri->rk.aux_prefix = bpi->extra->vnc.import.aux_prefix; } - if (rfapiGetUnAddrOfVpnBi(bi, &ri->un)) { + if (rfapiGetUnAddrOfVpnBi(bpi, &ri->un)) { rfapi_info_free(ri); continue; } @@ -1711,7 +1711,7 @@ void rfapiRibUpdatePendingNode( continue; } - rfapiRibBi2Ri(bi, ri, lifetime); + rfapiRibBi2Ri(bpi, ri, lifetime); if (!pn->info) { pn->info = list_new(); diff --git a/bgpd/rfapi/rfapi_rib.h b/bgpd/rfapi/rfapi_rib.h index a8872295cd..38a6df9fbf 100644 --- a/bgpd/rfapi/rfapi_rib.h +++ b/bgpd/rfapi/rfapi_rib.h @@ -105,7 +105,7 @@ extern void rfapiRibUpdatePendingNodeSubtree(struct bgp *bgp, extern int rfapiRibPreloadBi(struct agg_node *rfd_rib_node, struct prefix *pfx_vn, struct prefix *pfx_un, - uint32_t lifetime, struct bgp_info *bi); + uint32_t lifetime, struct bgp_path_info *bpi); extern struct rfapi_next_hop_entry * rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd, diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c index 1af9479a6a..1844839f25 100644 --- a/bgpd/rfapi/rfapi_vty.c +++ b/bgpd/rfapi/rfapi_vty.c @@ -394,7 +394,7 @@ int rfapiStream2Vty(void *stream, /* input */ /* called from bgpd/bgp_vty.c'route_vty_out() */ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, - struct bgp_info *bi, safi_t safi) + struct bgp_path_info *bpi, safi_t safi) { char *s; uint32_t lifetime; @@ -410,7 +410,7 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, if (safi == SAFI_MPLS_VPN) { struct prefix pfx_un; - if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) { + if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) { char buf[BUFSIZ]; vty_out(vty, "UN=%s", inet_ntop(pfx_un.family, pfx_un.u.val, buf, @@ -418,27 +418,27 @@ void rfapi_vty_out_vncinfo(struct vty *vty, struct prefix *p, } } - if (bi->attr && bi->attr->ecommunity) { - s = ecommunity_ecom2str(bi->attr->ecommunity, + if (bpi->attr && bpi->attr->ecommunity) { + s = ecommunity_ecom2str(bpi->attr->ecommunity, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); vty_out(vty, " EC{%s}", s); XFREE(MTYPE_ECOMMUNITY_STR, s); } - if (bi->extra != NULL) { - if (bi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK) + if (bpi->extra != NULL) { + if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK) vty_out(vty, " label=VRF2VRF"); else vty_out(vty, " label=%u", - decode_label(&bi->extra->label[0])); + decode_label(&bpi->extra->label[0])); } - if (!rfapiGetVncLifetime(bi->attr, &lifetime)) { + if (!rfapiGetVncLifetime(bpi->attr, &lifetime)) { vty_out(vty, " life=%d", lifetime); } - vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bi->type), - bi->sub_type); + vty_out(vty, " type=%s, subtype=%d", zebra_route_string(bpi->type), + bpi->sub_type); vty_out(vty, "%s", HVTYNL); } @@ -477,9 +477,9 @@ void rfapiPrintAttrPtrs(void *stream, struct attr *attr) } /* - * Print BI in an Import Table + * Print BPI in an Import Table */ -void rfapiPrintBi(void *stream, struct bgp_info *bi) +void rfapiPrintBi(void *stream, struct bgp_path_info *bpi) { char buf[BUFSIZ]; char *s; @@ -503,12 +503,13 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) return; - if (!bi) + if (!bpi) return; - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra - && bi->extra->vnc.import.timer) { - struct thread *t = (struct thread *)bi->extra->vnc.import.timer; + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra + && bpi->extra->vnc.import.timer) { + struct thread *t = + (struct thread *)bpi->extra->vnc.import.timer; r = snprintf(p, REMAIN, " [%4lu] ", thread_timer_remain_second(t)); INCP; @@ -518,14 +519,14 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) INCP; } - if (bi->extra) { + if (bpi->extra) { /* TBD This valid only for SAFI_MPLS_VPN, but not for encap */ - if (decode_rd_type(bi->extra->vnc.import.rd.val) + if (decode_rd_type(bpi->extra->vnc.import.rd.val) == RD_TYPE_VNC_ETH) { has_macaddr = 1; - memcpy(macaddr.octet, bi->extra->vnc.import.rd.val + 2, + memcpy(macaddr.octet, bpi->extra->vnc.import.rd.val + 2, 6); - l2hid = bi->extra->vnc.import.rd.val[1]; + l2hid = bpi->extra->vnc.import.rd.val[1]; } } @@ -537,24 +538,24 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) * RFP option sizes (they are opaque values) * extended communities (RTs) */ - if (bi->attr) { + if (bpi->attr) { uint32_t lifetime; int printed_1st_gol = 0; struct bgp_attr_encap_subtlv *pEncap; struct prefix pfx_un; - int af = BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len); + int af = BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len); /* Nexthop */ if (af == AF_INET) { r = snprintf(p, REMAIN, "%s", inet_ntop(AF_INET, - &bi->attr->mp_nexthop_global_in, + &bpi->attr->mp_nexthop_global_in, buf, BUFSIZ)); INCP; } else if (af == AF_INET6) { r = snprintf(p, REMAIN, "%s", inet_ntop(AF_INET6, - &bi->attr->mp_nexthop_global, + &bpi->attr->mp_nexthop_global, buf, BUFSIZ)); INCP; } else { @@ -565,7 +566,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) /* * VNC tunnel subtlv, if present, contains UN address */ - if (!rfapiGetVncTunnelUnAddr(bi->attr, &pfx_un)) { + if (!rfapiGetVncTunnelUnAddr(bpi->attr, &pfx_un)) { r = snprintf(p, REMAIN, " un=%s", inet_ntop(pfx_un.family, pfx_un.u.val, buf, BUFSIZ)); @@ -573,7 +574,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } /* Lifetime */ - if (rfapiGetVncLifetime(bi->attr, &lifetime)) { + if (rfapiGetVncLifetime(bpi->attr, &lifetime)) { r = snprintf(p, REMAIN, " nolife"); INCP; } else { @@ -585,7 +586,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } /* RFP option lengths */ - for (pEncap = bi->attr->vnc_subtlvs; pEncap; + for (pEncap = bpi->attr->vnc_subtlvs; pEncap; pEncap = pEncap->next) { if (pEncap->type == BGP_VNC_SUBTLV_TYPE_RFPOPTION) { @@ -604,8 +605,8 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } /* RT list */ - if (bi->attr->ecommunity) { - s = ecommunity_ecom2str(bi->attr->ecommunity, + if (bpi->attr->ecommunity) { + s = ecommunity_ecom2str(bpi->attr->ecommunity, ECOMMUNITY_FORMAT_ROUTE_MAP, 0); r = snprintf(p, REMAIN, " %s", s); INCP; @@ -613,13 +614,13 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } } - r = snprintf(p, REMAIN, " bi@%p", bi); + r = snprintf(p, REMAIN, " bpi@%p", bpi); INCP; - r = snprintf(p, REMAIN, " p@%p", bi->peer); + r = snprintf(p, REMAIN, " p@%p", bpi->peer); INCP; - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) { r = snprintf(p, REMAIN, " HD=yes"); INCP; } else { @@ -627,15 +628,16 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) INCP; } - if (bi->attr) { + if (bpi->attr) { - if (bi->attr->weight) { - r = snprintf(p, REMAIN, " W=%d", bi->attr->weight); + if (bpi->attr->weight) { + r = snprintf(p, REMAIN, " W=%d", bpi->attr->weight); INCP; } - if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { - r = snprintf(p, REMAIN, " LP=%d", bi->attr->local_pref); + if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { + r = snprintf(p, REMAIN, " LP=%d", + bpi->attr->local_pref); INCP; } else { r = snprintf(p, REMAIN, " LP=unset"); @@ -643,8 +645,8 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } } - r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bi->type), - bi->sub_type); + r = snprintf(p, REMAIN, " %c:%u", zebra_route_char(bpi->type), + bpi->sub_type); INCP; fp(out, "%s%s", line, HVTYNL); @@ -656,7 +658,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) HVTYNL); } - if (!rfapiGetL2o(bi->attr, &l2o_buf)) { + if (!rfapiGetL2o(bpi->attr, &l2o_buf)) { fp(out, " L2O ETH=%02x:%02x:%02x:%02x:%02x:%02x LBL=%d LNI=%d LHI=%hhu%s", l2o_buf.macaddr.octet[0], l2o_buf.macaddr.octet[1], @@ -665,12 +667,12 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) l2o_buf.label, l2o_buf.logical_net_id, l2o_buf.local_nve_id, HVTYNL); } - if (bi->extra && bi->extra->vnc.import.aux_prefix.family) { + if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) { const char *sp; - sp = rfapi_ntop(bi->extra->vnc.import.aux_prefix.family, - &bi->extra->vnc.import.aux_prefix.u.prefix, buf, - BUFSIZ); + sp = rfapi_ntop(bpi->extra->vnc.import.aux_prefix.family, + &bpi->extra->vnc.import.aux_prefix.u.prefix, + buf, BUFSIZ); buf[BUFSIZ - 1] = 0; if (sp) { fp(out, " IP: %s%s", sp, HVTYNL); @@ -678,7 +680,7 @@ void rfapiPrintBi(void *stream, struct bgp_info *bi) } { struct rfapi_un_option *uo = - rfapi_encap_tlv_to_un_option(bi->attr); + rfapi_encap_tlv_to_un_option(bpi->attr); if (uo) { rfapi_print_tunneltype_option(stream, 8, &uo->v.tunnel); rfapi_un_options_free(uo); @@ -734,13 +736,13 @@ static void rfapiDebugPrintMonitorEncap(void *stream, if (rfapiStream2Vty(stream, &fp, &vty, &out, &vty_newline) == 0) return; - fp(out, " Mon m=%p, next=%p, node=%p, bi=%p%s", m, m->next, m->node, - m->bi, HVTYNL); + fp(out, " Mon m=%p, next=%p, node=%p, bpi=%p%s", m, m->next, m->node, + m->bpi, HVTYNL); } void rfapiShowItNode(void *stream, struct agg_node *rn) { - struct bgp_info *bi; + struct bgp_path_info *bpi; char buf[BUFSIZ]; int (*fp)(void *, const char *, ...); @@ -755,8 +757,8 @@ void rfapiShowItNode(void *stream, struct agg_node *rn) rfapi_ntop(rn->p.family, &rn->p.u.prefix, buf, BUFSIZ), rn->p.prefixlen, rn, rn->lock, HVTYNL); - for (bi = rn->info; bi; bi = bi->next) { - rfapiPrintBi(stream, bi); + for (bpi = rn->info; bpi; bpi = bpi->next) { + rfapiPrintBi(stream, bpi); } /* doesn't show montors */ @@ -779,7 +781,7 @@ void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt, fp(out, "Import Table [%s]%s", label, HVTYNL); for (rn = agg_route_top(rt); rn; rn = agg_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; if (rn->p.family == AF_ETHERNET) { rfapiEthAddr2Str(&rn->p.u.prefix_eth, buf, BUFSIZ); @@ -791,8 +793,8 @@ void rfapiShowImportTable(void *stream, const char *label, struct agg_table *rt, rn->lock - 1, /* account for loop iterator locking */ HVTYNL); - for (bi = rn->info; bi; bi = bi->next) { - rfapiPrintBi(stream, bi); + for (bpi = rn->info; bpi; bpi = bpi->next) { + rfapiPrintBi(stream, bpi); } if (isvpn) { @@ -1008,7 +1010,7 @@ int rfapiShowVncQueries(void *stream, struct prefix *pfx_match) } static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, - struct agg_node *rn, struct bgp_info *bi) + struct agg_node *rn, struct bgp_path_info *bpi) { int (*fp)(void *, const char *, ...); struct vty *vty; @@ -1047,26 +1049,26 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, * UN addr */ buf_un[0] = 0; - if (!rfapiGetUnAddrOfVpnBi(bi, &pfx_un)) { + if (!rfapiGetUnAddrOfVpnBi(bpi, &pfx_un)) { snprintf(buf_un, BUFSIZ, "%s", inet_ntop(pfx_un.family, &pfx_un.u.prefix, buf_ntop, BUFSIZ)); } - rfapiGetTunnelType(bi->attr, &tun_type); + rfapiGetTunnelType(bpi->attr, &tun_type); /* * VN addr */ buf_vn[0] = 0; - rfapiNexthop2Prefix(bi->attr, &pfx_vn); + rfapiNexthop2Prefix(bpi->attr, &pfx_vn); if (tun_type == BGP_ENCAP_TYPE_MPLS) { /* MPLS carries un in nrli next hop (same as vn for IP tunnels) */ snprintf(buf_un, BUFSIZ, "%s", inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop, BUFSIZ)); - if (bi->extra) { - uint32_t l = decode_label(&bi->extra->label[0]); + if (bpi->extra) { + uint32_t l = decode_label(&bpi->extra->label[0]); snprintf(buf_vn, BUFSIZ, "Label: %d", l); } else /* should never happen */ { @@ -1085,10 +1087,10 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, * See rfapi_import.c'rfapiRouteInfo2NextHopEntry() for conversion * back to cost. */ - if (bi->attr) { + if (bpi->attr) { uint32_t local_pref; - if (bi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) - local_pref = bi->attr->local_pref; + if (bpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) + local_pref = bpi->attr->local_pref; else local_pref = 0; cost = (local_pref > 255) ? 0 : 255 - local_pref; @@ -1103,7 +1105,7 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, /* Lifetime */ /* NB rfapiGetVncLifetime sets infinite value when returning !0 */ - if (rfapiGetVncLifetime(bi->attr, &lifetime) + if (rfapiGetVncLifetime(bpi->attr, &lifetime) || (lifetime == RFAPI_INFINITE_LIFETIME)) { fp(out, "%-10s ", "infinite"); @@ -1113,20 +1115,21 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, fp(out, "%-10s ", buf_lifetime); } - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED) && bi->extra - && bi->extra->vnc.import.timer) { + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED) && bpi->extra + && bpi->extra->vnc.import.timer) { uint32_t remaining; time_t age; char buf_age[BUFSIZ]; - struct thread *t = (struct thread *)bi->extra->vnc.import.timer; + struct thread *t = + (struct thread *)bpi->extra->vnc.import.timer; remaining = thread_timer_remain_second(t); #if RFAPI_REGISTRATIONS_REPORT_AGE /* * Calculate when the timer started. Doing so here saves - * us a timestamp field in "struct bgp_info". + * us a timestamp field in "struct bgp_path_info". * * See rfapi_import.c'rfapiBiStartWithdrawTimer() for the * original calculation. @@ -1140,12 +1143,12 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, fp(out, "%-10s ", buf_age); - } else if (RFAPI_LOCAL_BI(bi)) { + } else if (RFAPI_LOCAL_BI(bpi)) { char buf_age[BUFSIZ]; - if (bi->extra && bi->extra->vnc.import.create_time) { - rfapiFormatAge(bi->extra->vnc.import.create_time, + if (bpi->extra && bpi->extra->vnc.import.create_time) { + rfapiFormatAge(bpi->extra->vnc.import.create_time, buf_age, BUFSIZ); } else { buf_age[0] = '?'; @@ -1161,12 +1164,12 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, * print that on the next line */ - if (bi->extra && bi->extra->vnc.import.aux_prefix.family) { + if (bpi->extra && bpi->extra->vnc.import.aux_prefix.family) { const char *sp; sp = rfapi_ntop( - bi->extra->vnc.import.aux_prefix.family, - &bi->extra->vnc.import.aux_prefix.u.prefix, + bpi->extra->vnc.import.aux_prefix.family, + &bpi->extra->vnc.import.aux_prefix.u.prefix, buf_ntop, BUFSIZ); buf_ntop[BUFSIZ - 1] = 0; @@ -1177,8 +1180,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream, } } } - if (tun_type != BGP_ENCAP_TYPE_MPLS && bi->extra) { - uint32_t l = decode_label(&bi->extra->label[0]); + if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) { + uint32_t l = decode_label(&bpi->extra->label[0]); if (!MPLS_LABEL_IS_NULL(l)) { fp(out, " Label: %d", l); if (nlines == 1) @@ -1222,7 +1225,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, for (rn = agg_route_top(it->imported_vpn[afi]); rn; rn = agg_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; int count_only; /* allow for wider or more narrow mask from user */ @@ -1232,30 +1235,32 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, else count_only = 0; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { - if (!show_local && RFAPI_LOCAL_BI(bi)) { + if (!show_local && RFAPI_LOCAL_BI(bpi)) { /* local route from RFP */ continue; } - if (!show_remote && !RFAPI_LOCAL_BI(bi)) { + if (!show_remote && !RFAPI_LOCAL_BI(bpi)) { /* remote route */ continue; } if (show_expiring - && !CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + && !CHECK_FLAG(bpi->flags, + BGP_PATH_REMOVED)) continue; if (!show_expiring - && CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; - if (bi->type == ZEBRA_ROUTE_BGP_DIRECT - || bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) { + if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT + || bpi->type + == ZEBRA_ROUTE_BGP_DIRECT_EXT) { if (!show_imported) continue; } else { @@ -1277,7 +1282,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, type = "Holddown"; } else { if (RFAPI_LOCAL_BI( - bi)) { + bpi)) { type = "Local"; } else { type = "Remote"; @@ -1327,7 +1332,7 @@ static int rfapiShowRemoteRegistrationsIt(struct bgp *bgp, void *stream, "Lifetime", agetype, HVTYNL); } printed += rfapiPrintRemoteRegBi(bgp, stream, - rn, bi); + rn, bpi); } } } @@ -1535,7 +1540,7 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd, { afi_t afi; /* of the VN address */ struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; uint8_t type = ZEBRA_ROUTE_BGP; struct bgp *bgp; int printed = 0; @@ -1543,7 +1548,7 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd, struct prefix_rd *prd; /* - * Find the bgp_info in the RIB corresponding to this + * Find the bgp_path in the RIB corresponding to this * prefix and rfd */ @@ -1565,12 +1570,12 @@ void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd, vty_out(vty, " bn=%p%s", bn, HVTYNL); - for (bi = bn->info; bi; bi = bi->next) { - if (bi->peer == rfd->peer && bi->type == type - && bi->sub_type == BGP_ROUTE_RFP && bi->extra - && bi->extra->vnc.export.rfapi_handle == (void *)rfd) { + for (bpi = bn->info; bpi; bpi = bpi->next) { + if (bpi->peer == rfd->peer && bpi->type == type + && bpi->sub_type == BGP_ROUTE_RFP && bpi->extra + && bpi->extra->vnc.export.rfapi_handle == (void *)rfd) { - rfapiPrintBi(vty, bi); + rfapiPrintBi(vty, bpi); printed = 1; } } @@ -4840,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 6fcae17a8a..212d394fdc 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -173,14 +173,14 @@ static int getce(struct bgp *bgp, struct attr *attr, struct prefix *pfx_ce) void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, - struct bgp_info *bi) + struct bgp_path_info *bpi) { - struct attr *attr = bi->attr; - struct peer *peer = bi->peer; + struct attr *attr = bpi->attr; + struct peer *peer = bpi->peer; struct prefix *prefix = &rn->p; afi_t afi = family2afi(prefix->family); struct bgp_node *urn; - struct bgp_info *ubi; + struct bgp_path_info *ubpi; struct attr hattr; struct attr *iattr; struct prefix ce_nexthop; @@ -193,10 +193,10 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, return; } - if ((bi->type != ZEBRA_ROUTE_BGP) - || (bi->sub_type != BGP_ROUTE_NORMAL - && bi->sub_type != BGP_ROUTE_RFP - && bi->sub_type != BGP_ROUTE_STATIC)) { + if ((bpi->type != ZEBRA_ROUTE_BGP) + || (bpi->sub_type != BGP_ROUTE_NORMAL + && bpi->sub_type != BGP_ROUTE_RFP + && bpi->sub_type != BGP_ROUTE_STATIC)) { vnc_zlog_debug_verbose( "%s: wrong route type/sub_type for export, skipping", @@ -256,17 +256,17 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, */ urn = bgp_afi_node_get(bgp->rib[afi][SAFI_UNICAST], afi, SAFI_UNICAST, prefix, NULL); - for (ubi = urn->info; ubi; ubi = ubi->next) { + for (ubpi = urn->info; ubpi; ubpi = ubpi->next) { struct prefix unicast_nexthop; - if (CHECK_FLAG(ubi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(ubpi->flags, BGP_PATH_REMOVED)) continue; - rfapiUnicastNexthop2Prefix(afi, ubi->attr, &unicast_nexthop); + rfapiUnicastNexthop2Prefix(afi, ubpi->attr, &unicast_nexthop); - if (ubi->type == ZEBRA_ROUTE_VNC_DIRECT - && ubi->sub_type == BGP_ROUTE_REDISTRIBUTE - && ubi->peer == peer + if (ubpi->type == ZEBRA_ROUTE_VNC_DIRECT + && ubpi->sub_type == BGP_ROUTE_REDISTRIBUTE + && ubpi->peer == peer && prefix_same(&unicast_nexthop, &ce_nexthop)) { vnc_zlog_debug_verbose( @@ -282,7 +282,7 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, */ encap_attr_export_ce(&hattr, attr, &ce_nexthop); if (bgp->rfapi_cfg->routemap_export_bgp) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -328,10 +328,10 @@ void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, * "Withdrawing a Route" export process */ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, - struct bgp_info *bi) + struct bgp_path_info *bpi) { afi_t afi = family2afi(rn->p.family); - struct bgp_info *vbi; + struct bgp_path_info *vbpi; struct prefix ce_nexthop; if (!afi) { @@ -364,7 +364,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, * This works only for IPv4 because IPv6 addresses are too big * to fit in an extended community */ - if (getce(bgp, bi->attr, &ce_nexthop)) { + if (getce(bgp, bpi->attr, &ce_nexthop)) { vnc_zlog_debug_verbose("%s: EC has no encoded CE, skipping", __func__); return; @@ -376,13 +376,13 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, * route from the unicast RIB */ - for (vbi = rn->info; vbi; vbi = vbi->next) { + for (vbpi = rn->info; vbpi; vbpi = vbpi->next) { struct prefix ce; - if (bi == vbi) + if (bpi == vbpi) continue; - if (bi->peer != vbi->peer) + if (bpi->peer != vbpi->peer) continue; - if (getce(bgp, vbi->attr, &ce)) + if (getce(bgp, vbpi->attr, &ce)) continue; if (prefix_same(&ce, &ce_nexthop)) { vnc_zlog_debug_verbose( @@ -395,8 +395,8 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, /* * withdraw the route */ - bgp_withdraw(bi->peer, &rn->p, 0, /* addpath_id */ - NULL, /* attr, ignored */ + bgp_withdraw(bpi->peer, &rn->p, 0, /* addpath_id */ + NULL, /* attr, ignored */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ NULL, 0, NULL); /* tag not used for unicast */ @@ -405,7 +405,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) { struct agg_node *rn; - struct bgp_info *ri; + struct bgp_path_info *ri; vnc_zlog_debug_verbose("%s: entry, afi=%d", __func__, afi); @@ -480,8 +480,8 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *ri; - struct bgp_info *next; + struct bgp_path_info *ri; + struct bgp_path_info *next; for (ri = rn->info, next = NULL; ri; ri = next) { @@ -516,24 +516,24 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) static struct ecommunity *vnc_route_origin_ecom(struct agg_node *rn) { struct ecommunity *new; - struct bgp_info *bi; + struct bgp_path_info *bpi; if (!rn->info) return NULL; new = ecommunity_new(); - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { struct ecommunity_val roec; - switch (BGP_MP_NEXTHOP_FAMILY(bi->attr->mp_nexthop_len)) { + switch (BGP_MP_NEXTHOP_FAMILY(bpi->attr->mp_nexthop_len)) { case AF_INET: memset(&roec, 0, sizeof(roec)); roec.val[0] = 0x01; roec.val[1] = 0x03; memcpy(roec.val + 2, - &bi->attr->mp_nexthop_global_in.s_addr, 4); + &bpi->attr->mp_nexthop_global_in.s_addr, 4); roec.val[6] = 0; roec.val[7] = 0; ecommunity_add_val(new, &roec); @@ -996,7 +996,7 @@ void vnc_direct_bgp_add_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) struct rfapi_descriptor *irfd = rfd; struct attr hattr; struct attr *iattr; - struct bgp_info info; + struct bgp_path_info info; if (rfapiRaddr2Qprefix(&irfd->vn_addr, &nhp)) @@ -1165,7 +1165,7 @@ static void vnc_direct_add_rn_group_rd(struct bgp *bgp, afi_t afi, struct rfapi_descriptor *irfd) { struct prefix nhp; - struct bgp_info info; + struct bgp_path_info info; struct attr hattr; struct attr *iattr; @@ -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) { @@ -1629,7 +1628,7 @@ void vnc_direct_bgp_vpn_disable(struct bgp *bgp, afi_t afi) /* * "Adding a Route" export process - * TBD do we need to check bi->type and bi->sub_type here, or does + * TBD do we need to check bpi->type and bpi->sub_type here, or does * caller do it? */ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi, @@ -1684,7 +1683,7 @@ void vnc_direct_bgp_rh_add_route(struct bgp *bgp, afi_t afi, if (encap_attr_export(&hattr, attr, NULL, NULL)) return; if (hc->routemap_export_bgp) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -1753,7 +1752,7 @@ static int vncExportWithdrawTimer(struct thread *t) /* * "Withdrawing a Route" export process - * TBD do we need to check bi->type and bi->sub_type here, or does + * TBD do we need to check bpi->type and bpi->sub_type here, or does * caller do it? */ void vnc_direct_bgp_rh_del_route(struct bgp *bgp, afi_t afi, @@ -1839,7 +1838,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) struct bgp_table *table; struct bgp_node *rn; - struct bgp_info *ri; + struct bgp_path_info *ri; memset(&prd, 0, sizeof(prd)); prd.family = AF_UNSPEC; @@ -1910,7 +1909,7 @@ void vnc_direct_bgp_rh_vpn_enable(struct bgp *bgp, afi_t afi) } if (hc->routemap_export_bgp) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -2001,8 +2000,8 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi) for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *ri; - struct bgp_info *next; + struct bgp_path_info *ri; + struct bgp_path_info *next; for (ri = rn->info, next = NULL; ri; ri = next) { diff --git a/bgpd/rfapi/vnc_export_bgp_p.h b/bgpd/rfapi/vnc_export_bgp_p.h index e074c3eaad..a1cb972740 100644 --- a/bgpd/rfapi/vnc_export_bgp_p.h +++ b/bgpd/rfapi/vnc_export_bgp_p.h @@ -30,10 +30,10 @@ #include "rfapi_private.h" extern void vnc_direct_bgp_add_route_ce(struct bgp *bgp, struct agg_node *rn, - struct bgp_info *bi); + struct bgp_path_info *bpi); extern void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, - struct bgp_info *bi); + struct bgp_path_info *bpi); extern void vnc_direct_bgp_add_prefix(struct bgp *bgp, struct rfapi_import_table *import_table, diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c index 8a286d1377..2f634f6f40 100644 --- a/bgpd/rfapi/vnc_import_bgp.c +++ b/bgpd/rfapi/vnc_import_bgp.c @@ -122,7 +122,7 @@ static int is_host_prefix(struct prefix *p) struct prefix_bag { struct prefix hpfx; /* ce address = unicast nexthop */ struct prefix upfx; /* unicast prefix */ - struct bgp_info *ubi; /* unicast route */ + struct bgp_path_info *ubpi; /* unicast route */ }; static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, @@ -217,8 +217,8 @@ static void print_rhn_list(const char *tag1, const char *tag2) prefix2str(&pb->upfx, ubuf, sizeof(ubuf)); vnc_zlog_debug_verbose( - "RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubi=%p", - ++count, p, kbuf, ubuf, hbuf, pb->ubi); + "RHN Entry %d (q=%p): kpfx=%s, upfx=%s, hpfx=%s, ubpi=%p", + ++count, p, kbuf, ubuf, hbuf, pb->ubpi); } } #endif @@ -253,10 +253,10 @@ static void vnc_rhnck(char *tag) afi = family2afi(pb->upfx.family); - rfapiUnicastNexthop2Prefix(afi, pb->ubi->attr, + rfapiUnicastNexthop2Prefix(afi, pb->ubpi->attr, &pfx_orig_nexthop); - /* pb->hpfx, pb->ubi nexthop, pkey should all reflect the same + /* pb->hpfx, pb->ubpi nexthop, pkey should all reflect the same * pfx */ assert(!vnc_prefix_cmp(&pb->hpfx, pkey)); if (vnc_prefix_cmp(&pb->hpfx, &pfx_orig_nexthop)) { @@ -267,7 +267,7 @@ static void vnc_rhnck(char *tag) prefix2str(&pb->hpfx, str_nve_pfx, sizeof(str_nve_pfx)); vnc_zlog_debug_verbose( - "%s: %s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + "%s: %s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s", __func__, tag, str_onh, str_nve_pfx); assert(0); } @@ -300,7 +300,7 @@ static void vnc_rhnck(char *tag) static int process_unicast_route(struct bgp *bgp, /* in */ afi_t afi, /* in */ struct prefix *prefix, /* in */ - struct bgp_info *info, /* in */ + struct bgp_path_info *info, /* in */ struct ecommunity **ecom, /* OUT */ struct prefix *unicast_nexthop) /* OUT */ { @@ -359,7 +359,7 @@ static int process_unicast_route(struct bgp *bgp, /* in */ bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ if (rmap) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -422,8 +422,8 @@ static int process_unicast_route(struct bgp *bgp, /* in */ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( - struct bgp *bgp, afi_t afi, struct bgp_info *bi, /* VPN bi */ - struct prefix_rd *prd, /* RD */ + struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */ + struct prefix_rd *prd, /* RD */ struct prefix *prefix, /* unicast route prefix */ uint32_t *local_pref, /* NULL = no local_pref */ uint32_t *med, /* NULL = no med */ @@ -443,20 +443,22 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( vnc_zlog_debug_verbose("%s: entry", __func__); - if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) { + if (bpi->type != ZEBRA_ROUTE_BGP + && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) { return; } - if (bi->sub_type != BGP_ROUTE_NORMAL && bi->sub_type != BGP_ROUTE_STATIC - && bi->sub_type != BGP_ROUTE_RFP) { + if (bpi->sub_type != BGP_ROUTE_NORMAL + && bpi->sub_type != BGP_ROUTE_STATIC + && bpi->sub_type != BGP_ROUTE_RFP) { return; } - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) return; - vncHDResolveNve.peer = bi->peer; - if (!rfapiGetVncTunnelUnAddr(bi->attr, &un)) { + vncHDResolveNve.peer = bpi->peer; + if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) { if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr)) return; } else { @@ -465,26 +467,26 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( } /* Use nexthop of VPN route as nexthop of constructed route */ - rfapiNexthop2Prefix(bi->attr, &nexthop); + rfapiNexthop2Prefix(bpi->attr, &nexthop); rfapiQprefix2Raddr(&nexthop, &nexthop_h); - if (rfapiGetVncLifetime(bi->attr, &lifetime)) { + if (rfapiGetVncLifetime(bpi->attr, &lifetime)) { plifetime = NULL; } else { plifetime = &lifetime; } - if (bi->attr) { - encaptlvs = bi->attr->vnc_subtlvs; - if (bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED - && bi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) { + if (bpi->attr) { + encaptlvs = bpi->attr->vnc_subtlvs; + if (bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_RESERVED + && bpi->attr->encap_tunneltype != BGP_ENCAP_TYPE_MPLS) { if (opt != NULL) opt->next = &optary[cur_opt]; opt = &optary[cur_opt++]; memset(opt, 0, sizeof(struct rfapi_un_option)); opt->type = RFAPI_UN_OPTION_TYPE_TUNNELTYPE; - opt->v.tunnel.type = bi->attr->encap_tunneltype; - /* TBD parse bi->attr->extra->encap_subtlvs */ + opt->v.tunnel.type = bpi->attr->encap_tunneltype; + /* TBD parse bpi->attr->extra->encap_subtlvs */ } } else { encaptlvs = NULL; @@ -492,11 +494,11 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi( struct ecommunity *new_ecom = ecommunity_dup(ecom); - if (bi->attr && bi->attr->ecommunity) - ecommunity_merge(new_ecom, bi->attr->ecommunity); + if (bpi->attr && bpi->attr->ecommunity) + ecommunity_merge(new_ecom, bpi->attr->ecommunity); - if (bi->extra) - label = decode_label(&bi->extra->label[0]); + if (bpi->extra) + label = decode_label(&bpi->extra->label[0]); add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN, prefix, /* unicast route prefix */ @@ -516,12 +518,12 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd( struct bgp_table *table_rd, /* per-rd VPN route table */ afi_t afi, struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ struct ecommunity *ecom, /* generated ecoms */ - uint32_t *local_pref, /* NULL = no local_pref */ - uint32_t *med, /* NULL = no med */ - struct prefix *ubi_nexthop) /* unicast nexthop */ + uint32_t *local_pref, /* NULL = no local_pref */ + uint32_t *med, /* NULL = no med */ + struct prefix *ubpi_nexthop) /* unicast nexthop */ { struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; if (!table_rd) return; @@ -529,24 +531,25 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd( { char str_nh[PREFIX_STRLEN]; - prefix2str(ubi_nexthop, str_nh, sizeof(str_nh)); + prefix2str(ubpi_nexthop, str_nh, sizeof(str_nh)); - vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__, str_nh); + vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__, str_nh); } /* exact match */ - bn = bgp_node_lookup(table_rd, ubi_nexthop); + bn = bgp_node_lookup(table_rd, ubpi_nexthop); if (!bn) { vnc_zlog_debug_verbose( - "%s: no match in RD's table for ubi_nexthop", __func__); + "%s: no match in RD's table for ubpi_nexthop", + __func__); return; } - /* Iterate over bgp_info items at this node */ - for (bi = bn->info; bi; bi = bi->next) { + /* Iterate over bgp_path_info items at this node */ + for (bpi = bn->info; bpi; bpi = bpi->next) { vnc_import_bgp_add_route_mode_resolve_nve_one_bi( - bgp, afi, bi, /* VPN bi */ + bgp, afi, bpi, /* VPN bpi */ prd, prefix, local_pref, med, ecom); } @@ -555,7 +558,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_rd( static void vnc_import_bgp_add_route_mode_resolve_nve( struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info) /* unicast info */ + struct bgp_path_info *info) /* unicast info */ { afi_t afi = family2afi(prefix->family); @@ -657,10 +660,10 @@ static void vnc_import_bgp_add_route_mode_resolve_nve( pb = XCALLOC(MTYPE_RFAPI_PREFIX_BAG, sizeof(struct prefix_bag)); pb->hpfx = pfx_unicast_nexthop; - pb->ubi = info; + pb->ubpi = info; pb->upfx = *prefix; - bgp_info_lock(info); /* skiplist refers to it */ + bgp_path_info_lock(info); /* skiplist refers to it */ skiplist_insert(bgp->rfapi->resolve_nve_nexthop, &pb->hpfx, pb); /* @@ -693,7 +696,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve( static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info) + struct bgp_path_info *info) { afi_t afi = family2afi(prefix->family); struct peer *peer = info->peer; @@ -808,7 +811,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ if (rmap) { - struct bgp_info info; + struct bgp_path_info info; route_map_result_t ret; memset(&info, 0, sizeof(info)); @@ -881,7 +884,7 @@ static void vnc_import_bgp_add_route_mode_plain(struct bgp *bgp, static void vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info, + struct bgp_path_info *info, struct rfapi_nve_group_cfg *rfg) { afi_t afi = family2afi(prefix->family); @@ -1010,13 +1013,13 @@ vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, bgp_attr_dup(&hattr, attr); /* hattr becomes a ghost attr */ if (rmap) { - struct bgp_info binfo; + struct bgp_path_info path; route_map_result_t ret; - memset(&binfo, 0, sizeof(binfo)); - binfo.peer = peer; - binfo.attr = &hattr; - ret = route_map_apply(rmap, prefix, RMAP_BGP, &binfo); + memset(&path, 0, sizeof(path)); + path.peer = peer; + path.attr = &hattr; + ret = route_map_apply(rmap, prefix, RMAP_BGP, &path); if (ret == RMAP_DENYMATCH) { bgp_attr_flush(&hattr); vnc_zlog_debug_verbose( @@ -1085,7 +1088,7 @@ vnc_import_bgp_add_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info) + struct bgp_path_info *info) { struct prefix_rd prd; afi_t afi = family2afi(prefix->family); @@ -1158,7 +1161,7 @@ static void vnc_import_bgp_del_route_mode_plain(struct bgp *bgp, static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info) + struct bgp_path_info *info) { struct prefix_rd prd; afi_t afi = family2afi(prefix->family); @@ -1238,26 +1241,28 @@ static void vnc_import_bgp_del_route_mode_nvegroup(struct bgp *bgp, } static void vnc_import_bgp_del_route_mode_resolve_nve_one_bi( - struct bgp *bgp, afi_t afi, struct bgp_info *bi, /* VPN bi */ - struct prefix_rd *prd, /* RD */ + struct bgp *bgp, afi_t afi, struct bgp_path_info *bpi, /* VPN bpi */ + struct prefix_rd *prd, /* RD */ struct prefix *prefix) /* unicast route prefix */ { struct prefix un; - if (bi->type != ZEBRA_ROUTE_BGP && bi->type != ZEBRA_ROUTE_BGP_DIRECT) { + if (bpi->type != ZEBRA_ROUTE_BGP + && bpi->type != ZEBRA_ROUTE_BGP_DIRECT) { return; } - if (bi->sub_type != BGP_ROUTE_NORMAL && bi->sub_type != BGP_ROUTE_STATIC - && bi->sub_type != BGP_ROUTE_RFP) { + if (bpi->sub_type != BGP_ROUTE_NORMAL + && bpi->sub_type != BGP_ROUTE_STATIC + && bpi->sub_type != BGP_ROUTE_RFP) { return; } - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) return; - vncHDResolveNve.peer = bi->peer; - if (!rfapiGetVncTunnelUnAddr(bi->attr, &un)) { + vncHDResolveNve.peer = bpi->peer; + if (!rfapiGetVncTunnelUnAddr(bpi->attr, &un)) { if (rfapiQprefix2Raddr(&un, &vncHDResolveNve.un_addr)) return; } else { @@ -1275,10 +1280,10 @@ static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd( struct prefix_rd *prd, struct bgp_table *table_rd, /* per-rd VPN route table */ afi_t afi, struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ - struct prefix *ubi_nexthop) /* unicast bi's nexthop */ + struct prefix *ubpi_nexthop) /* unicast bpi's nexthop */ { struct bgp_node *bn; - struct bgp_info *bi; + struct bgp_path_info *bpi; if (!table_rd) return; @@ -1286,35 +1291,36 @@ static void vnc_import_bgp_del_route_mode_resolve_nve_one_rd( { char str_nh[PREFIX_STRLEN]; - prefix2str(ubi_nexthop, str_nh, sizeof(str_nh)); - vnc_zlog_debug_verbose("%s: ubi_nexthop=%s", __func__, str_nh); + prefix2str(ubpi_nexthop, str_nh, sizeof(str_nh)); + vnc_zlog_debug_verbose("%s: ubpi_nexthop=%s", __func__, str_nh); } /* exact match */ - bn = bgp_node_lookup(table_rd, ubi_nexthop); + bn = bgp_node_lookup(table_rd, ubpi_nexthop); if (!bn) { vnc_zlog_debug_verbose( - "%s: no match in RD's table for ubi_nexthop", __func__); + "%s: no match in RD's table for ubpi_nexthop", + __func__); return; } - /* Iterate over bgp_info items at this node */ - for (bi = bn->info; bi; bi = bi->next) { + /* Iterate over bgp_path_info items at this node */ + for (bpi = bn->info; bpi; bpi = bpi->next) { vnc_import_bgp_del_route_mode_resolve_nve_one_bi( - bgp, afi, bi, /* VPN bi */ - prd, /* VPN RD */ - prefix); /* unicast route prefix */ + bgp, afi, bpi, /* VPN bpi */ + prd, /* VPN RD */ + prefix); /* unicast route prefix */ } bgp_unlock_node(bn); } -static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, - afi_t afi, - struct prefix *prefix, - struct bgp_info *info) +static void +vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, afi_t afi, + struct prefix *prefix, + struct bgp_path_info *info) { struct ecommunity *ecom = NULL; struct prefix pfx_unicast_nexthop = {0}; /* happy valgrind */ @@ -1352,9 +1358,9 @@ static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, rc = skiplist_first_value(sl, &pfx_unicast_nexthop, (void *)&pb, &cursor); while (!rc) { - if (pb->ubi == info) { + if (pb->ubpi == info) { skiplist_delete(sl, &pfx_unicast_nexthop, pb); - bgp_info_unlock(info); + bgp_path_info_unlock(info); break; } rc = skiplist_next_value(sl, &pfx_unicast_nexthop, (void *)&pb, @@ -1391,14 +1397,14 @@ static void vnc_import_bgp_del_route_mode_resolve_nve(struct bgp *bgp, ***********************************************************************/ /* - * Should be called whan a bi is added to VPN RIB. This function + * Should be called whan a bpi is added to VPN RIB. This function * will check if it is a host route and return immediately if not. */ void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( struct bgp *bgp, struct prefix_rd *prd, /* RD */ struct bgp_table *table_rd, /* per-rd VPN route table */ struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi) /* new VPN host route */ + struct bgp_path_info *bpi) /* new VPN host route */ { afi_t afi = family2afi(prefix->family); struct skiplist *sl = NULL; @@ -1469,11 +1475,11 @@ void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( prefix2str(&pb->upfx, ubuf, sizeof(ubuf)); vnc_zlog_debug_any( - "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubi=%p", - __func__, cursor, ubuf, hbuf, pb->ubi); + "%s: examining RHN Entry (q=%p): upfx=%s, hpfx=%s, ubpi=%p", + __func__, cursor, ubuf, hbuf, pb->ubpi); } - if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubi, &ecom, + if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom, &pfx_unicast_nexthop)) { vnc_zlog_debug_verbose( @@ -1481,13 +1487,13 @@ void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( __func__); continue; } - local_pref = calc_local_pref(pb->ubi->attr, pb->ubi->peer); + local_pref = calc_local_pref(pb->ubpi->attr, pb->ubpi->peer); - if (pb->ubi->attr - && (pb->ubi->attr->flag + if (pb->ubpi->attr + && (pb->ubpi->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))) { - med = &pb->ubi->attr->med; + med = &pb->ubpi->attr->med; } /* @@ -1502,13 +1508,13 @@ void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( prefix2str(prefix, str_nve_pfx, sizeof(str_nve_pfx)); vnc_zlog_debug_verbose( - "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s", __func__, str_unh, str_nve_pfx); assert(0); } vnc_import_bgp_add_route_mode_resolve_nve_one_bi( - bgp, afi, bi, /* VPN bi */ + bgp, afi, bpi, /* VPN bpi */ prd, &pb->upfx, /* unicast prefix */ &local_pref, med, ecom); @@ -1538,7 +1544,7 @@ void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( struct bgp *bgp, struct prefix_rd *prd, /* RD */ struct bgp_table *table_rd, /* per-rd VPN route table */ struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi) /* old VPN host route */ + struct bgp_path_info *bpi) /* old VPN host route */ { afi_t afi = family2afi(prefix->family); struct skiplist *sl = NULL; @@ -1605,7 +1611,7 @@ void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( memset(&pfx_unicast_nexthop, 0, sizeof(struct prefix)); /* keep valgrind happy */ - if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubi, &ecom, + if (process_unicast_route(bgp, afi, &pb->upfx, pb->ubpi, &ecom, &pfx_unicast_nexthop)) { vnc_zlog_debug_verbose( @@ -1626,13 +1632,13 @@ void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( prefix2str(prefix, str_nve_pfx, sizeof(str_nve_pfx)); vnc_zlog_debug_verbose( - "%s: FATAL: resolve_nve_nexthop list item bi nexthop %s != nve pfx %s", + "%s: FATAL: resolve_nve_nexthop list item bpi nexthop %s != nve pfx %s", __func__, str_unh, str_nve_pfx); assert(0); } vnc_import_bgp_del_route_mode_resolve_nve_one_bi( - bgp, afi, bi, prd, &pb->upfx); + bgp, afi, bpi, prd, &pb->upfx); if (ecom) ecommunity_free(&ecom); @@ -1648,19 +1654,19 @@ void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( #define DEBUG_IS_USABLE_INTERIOR 1 -static int is_usable_interior_route(struct bgp_info *bi_interior) +static int is_usable_interior_route(struct bgp_path_info *bpi_interior) { - if (!VALID_INTERIOR_TYPE(bi_interior->type)) { + if (!VALID_INTERIOR_TYPE(bpi_interior->type)) { #if DEBUG_IS_USABLE_INTERIOR vnc_zlog_debug_verbose( "%s: NO: type %d is not valid interior type", __func__, - bi_interior->type); + bpi_interior->type); #endif return 0; } - if (!CHECK_FLAG(bi_interior->flags, BGP_INFO_VALID)) { + if (!CHECK_FLAG(bpi_interior->flags, BGP_PATH_VALID)) { #if DEBUG_IS_USABLE_INTERIOR - vnc_zlog_debug_verbose("%s: NO: BGP_INFO_VALID not set", + vnc_zlog_debug_verbose("%s: NO: BGP_PATH_VALID not set", __func__); #endif return 0; @@ -1680,7 +1686,7 @@ static int is_usable_interior_route(struct bgp_info *bi_interior) static void vnc_import_bgp_exterior_add_route_it( struct bgp *bgp, /* exterior instance, we hope */ struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info, /* unicast info */ + struct bgp_path_info *info, /* unicast info */ struct rfapi_import_table *it_only) /* NULL, or limit to this IT */ { struct rfapi *h; @@ -1740,7 +1746,7 @@ static void vnc_import_bgp_exterior_add_route_it( struct agg_table *table; struct agg_node *rn; struct agg_node *par; - struct bgp_info *bi_interior; + struct bgp_path_info *bpi_interior; int have_usable_route; vnc_zlog_debug_verbose("%s: doing it %p", __func__, it); @@ -1760,18 +1766,18 @@ static void vnc_import_bgp_exterior_add_route_it( vnc_zlog_debug_verbose("%s: it %p trying rn %p", __func__, it, rn); - for (bi_interior = rn->info; bi_interior; - bi_interior = bi_interior->next) { + for (bpi_interior = rn->info; bpi_interior; + bpi_interior = bpi_interior->next) { struct prefix_rd *prd; struct attr new_attr; uint32_t label = 0; - if (!is_usable_interior_route(bi_interior)) + if (!is_usable_interior_route(bpi_interior)) continue; vnc_zlog_debug_verbose( - "%s: usable: bi_interior %p", __func__, - bi_interior); + "%s: usable: bpi_interior %p", __func__, + bpi_interior); /* * have a legitimate route to exterior's nexthop @@ -1781,17 +1787,17 @@ static void vnc_import_bgp_exterior_add_route_it( */ have_usable_route = 1; - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import .rd; label = decode_label( - &bi_interior->extra->label[0]); + &bpi_interior->extra->label[0]); } else prd = NULL; /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bi_interior->attr); + bgp_attr_dup(&new_attr, bpi_interior->attr); if (info->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) { new_attr.local_pref = @@ -1802,7 +1808,7 @@ static void vnc_import_bgp_exterior_add_route_it( rfapiBgpInfoFilteredImportVPN( it, FIF_ACTION_UPDATE, - bi_interior->peer, NULL, /* rfd */ + bpi_interior->peer, NULL, /* rfd */ prefix, NULL, afi, prd, &new_attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, &label); @@ -1829,7 +1835,7 @@ static void vnc_import_bgp_exterior_add_route_it( RFAPI_MONITOR_EXTERIOR(rn)->source, info, pfx_mon)) { - bgp_info_lock(info); + bgp_path_info_lock(info); } } par = agg_node_parent(rn); @@ -1847,16 +1853,16 @@ static void vnc_import_bgp_exterior_add_route_it( if (!skiplist_insert(it->monitor_exterior_orphans, info, pfx_mon)) { - bgp_info_lock(info); + bgp_path_info_lock(info); } } } } void vnc_import_bgp_exterior_add_route( - struct bgp *bgp, /* exterior instance, we hope */ - struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info) /* unicast info */ + struct bgp *bgp, /* exterior instance, we hope */ + struct prefix *prefix, /* unicast prefix */ + struct bgp_path_info *info) /* unicast info */ { vnc_import_bgp_exterior_add_route_it(bgp, prefix, info, NULL); } @@ -1872,7 +1878,7 @@ void vnc_import_bgp_exterior_add_route( */ void vnc_import_bgp_exterior_del_route( struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info) /* unicast info */ + struct bgp_path_info *info) /* unicast info */ { struct rfapi *h; struct rfapi_cfg *hc; @@ -1931,7 +1937,7 @@ void vnc_import_bgp_exterior_del_route( struct agg_table *table; struct agg_node *rn; struct agg_node *par; - struct bgp_info *bi_interior; + struct bgp_path_info *bpi_interior; int have_usable_route; table = it->imported_vpn[afi]; @@ -1940,12 +1946,12 @@ void vnc_import_bgp_exterior_del_route( have_usable_route = 0; (!have_usable_route) && rn;) { - for (bi_interior = rn->info; bi_interior; - bi_interior = bi_interior->next) { + for (bpi_interior = rn->info; bpi_interior; + bpi_interior = bpi_interior->next) { struct prefix_rd *prd; uint32_t label = 0; - if (!is_usable_interior_route(bi_interior)) + if (!is_usable_interior_route(bpi_interior)) continue; /* @@ -1956,19 +1962,19 @@ void vnc_import_bgp_exterior_del_route( */ have_usable_route = 1; - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import .rd; label = decode_label( - &bi_interior->extra->label[0]); + &bpi_interior->extra->label[0]); } else prd = NULL; rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_KILL, bi_interior->peer, + it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */ prefix, NULL, afi, prd, - bi_interior->attr, + bpi_interior->attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, &label); @@ -1986,7 +1992,8 @@ void vnc_import_bgp_exterior_del_route( ->source, info, NULL)) { - bgp_info_unlock(info); + bgp_path_info_unlock( + info); agg_unlock_node( rn); /* sl entry */ @@ -2023,7 +2030,7 @@ void vnc_import_bgp_exterior_del_route( if (!skiplist_delete(it->monitor_exterior_orphans, info, NULL)) { - bgp_info_unlock(info); + bgp_path_info_unlock(info); } } } @@ -2038,12 +2045,12 @@ void vnc_import_bgp_exterior_del_route( */ void vnc_import_bgp_exterior_add_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct agg_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_path_info *bpi_interior) /* VPN IT route */ { afi_t afi = family2afi(rn_interior->p.family); struct agg_node *par; - struct bgp_info *bi_exterior; + struct bgp_path_info *bpi_exterior; struct prefix *pfx_exterior; /* exterior pfx */ void *cursor; int rc; @@ -2051,7 +2058,7 @@ void vnc_import_bgp_exterior_add_route_interior( vnc_zlog_debug_verbose("%s: entry", __func__); - if (!is_usable_interior_route(bi_interior)) { + if (!is_usable_interior_route(bpi_interior)) { vnc_zlog_debug_verbose( "%s: not usable interior route, skipping", __func__); return; @@ -2075,8 +2082,8 @@ void vnc_import_bgp_exterior_add_route_interior( char str_pfx[PREFIX_STRLEN]; prefix2str(&rn_interior->p, str_pfx, sizeof(str_pfx)); - vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d", - __func__, str_pfx, bi_interior->type); + vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d", + __func__, str_pfx, bpi_interior->type); } if (RFAPI_HAS_MONITOR_EXTERIOR(rn_interior)) { @@ -2095,12 +2102,12 @@ void vnc_import_bgp_exterior_add_route_interior( cursor = NULL; for (rc = skiplist_next( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, (void **)&pfx_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor); !rc; rc = skiplist_next( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, (void **)&pfx_exterior, - &cursor)) { + (void **)&bpi_exterior, + (void **)&pfx_exterior, &cursor)) { struct prefix_rd *prd; struct attr new_attr; @@ -2109,30 +2116,30 @@ void vnc_import_bgp_exterior_add_route_interior( ++count; /* debugging */ - assert(bi_exterior); + assert(bpi_exterior); assert(pfx_exterior); - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import.rd; + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import.rd; label = decode_label( - &bi_interior->extra->label[0]); + &bpi_interior->extra->label[0]); } else prd = NULL; /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bi_interior->attr); - if (bi_exterior - && (bi_exterior->attr->flag + bgp_attr_dup(&new_attr, bpi_interior->attr); + if (bpi_exterior + && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { new_attr.local_pref = - bi_exterior->attr->local_pref; + bpi_exterior->attr->local_pref; new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); } rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_UPDATE, bi_interior->peer, + it, FIF_ACTION_UPDATE, bpi_interior->peer, NULL, /* rfd */ pfx_exterior, NULL, afi, prd, &new_attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, @@ -2176,11 +2183,11 @@ void vnc_import_bgp_exterior_add_route_interior( /* check monitors at par for possible pulldown */ cursor = NULL; for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source, - (void **)&bi_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor); !rc; rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(par)->source, - (void **)&bi_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor)) { struct prefix pfx_nexthop; @@ -2189,12 +2196,12 @@ void vnc_import_bgp_exterior_add_route_interior( sizeof(struct prefix)); /* keep valgrind happy */ /* check original nexthop for prefix match */ - rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr, + rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr, &pfx_nexthop); if (prefix_match(&rn_interior->p, &pfx_nexthop)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; struct prefix_rd *prd; struct attr new_attr; uint32_t label = 0; @@ -2217,27 +2224,28 @@ void vnc_import_bgp_exterior_add_route_interior( skiplist_insert( RFAPI_MONITOR_EXTERIOR(rn_interior) ->source, - bi_exterior, pfx_mon); + bpi_exterior, pfx_mon); agg_lock_node(rn_interior); /* * Delete constructed exterior routes based on * parent routes. */ - for (bi = par->info; bi; bi = bi->next) { + for (bpi = par->info; bpi; bpi = bpi->next) { - if (bi->extra) { - prd = &bi->extra->vnc.import.rd; + if (bpi->extra) { + prd = &bpi->extra->vnc.import + .rd; label = decode_label( - &bi->extra->label[0]); + &bpi->extra->label[0]); } else prd = NULL; rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_KILL, bi->peer, + it, FIF_ACTION_KILL, bpi->peer, NULL, /* rfd */ pfx_exterior, NULL, afi, prd, - bi->attr, + bpi->attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, &label); } @@ -2247,29 +2255,29 @@ void vnc_import_bgp_exterior_add_route_interior( * Add constructed exterior routes based on * the new interior route at longer prefix. */ - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import .rd; label = decode_label( - &bi_interior->extra->label[0]); + &bpi_interior->extra->label[0]); } else prd = NULL; /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bi_interior->attr); - if (bi_exterior - && (bi_exterior->attr->flag + bgp_attr_dup(&new_attr, bpi_interior->attr); + if (bpi_exterior + && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { new_attr.local_pref = - bi_exterior->attr->local_pref; + bpi_exterior->attr->local_pref; new_attr.flag |= ATTR_FLAG_BIT( BGP_ATTR_LOCAL_PREF); } rfapiBgpInfoFilteredImportVPN( it, FIF_ACTION_UPDATE, - bi_interior->peer, NULL, /* rfd */ + bpi_interior->peer, NULL, /* rfd */ pfx_exterior, NULL, afi, prd, &new_attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, &label); @@ -2284,14 +2292,14 @@ void vnc_import_bgp_exterior_add_route_interior( cursor = NULL; for (rc = skiplist_next( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, NULL, &cursor); + (void **)&bpi_exterior, NULL, &cursor); !rc; rc = skiplist_next( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, NULL, &cursor)) { + (void **)&bpi_exterior, NULL, &cursor)) { skiplist_delete(RFAPI_MONITOR_EXTERIOR(par)->source, - bi_exterior, NULL); + bpi_exterior, NULL); agg_unlock_node(par); /* sl entry */ } if (skiplist_empty(RFAPI_MONITOR_EXTERIOR(par)->source)) { @@ -2309,10 +2317,10 @@ void vnc_import_bgp_exterior_add_route_interior( cursor = NULL; list_adopted = NULL; for (rc = skiplist_next(it->monitor_exterior_orphans, - (void **)&bi_exterior, (void **)&pfx_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor); !rc; rc = skiplist_next(it->monitor_exterior_orphans, - (void **)&bi_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor)) { struct prefix pfx_nexthop; @@ -2332,7 +2340,7 @@ void vnc_import_bgp_exterior_add_route_interior( } /* check original nexthop for prefix match */ - rfapiUnicastNexthop2Prefix(afi, bi_exterior->attr, + rfapiUnicastNexthop2Prefix(afi, bpi_exterior->attr, &pfx_nexthop); if (prefix_match(&rn_interior->p, &pfx_nexthop)) { @@ -2358,38 +2366,38 @@ void vnc_import_bgp_exterior_add_route_interior( } skiplist_insert( RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - bi_exterior, pfx_mon); + bpi_exterior, pfx_mon); agg_lock_node(rn_interior); /* sl entry */ if (!list_adopted) { list_adopted = list_new(); } - listnode_add(list_adopted, bi_exterior); + listnode_add(list_adopted, bpi_exterior); /* * Add constructed exterior routes based on the * new interior route at the longer prefix. */ - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import.rd; + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import.rd; label = decode_label( - &bi_interior->extra->label[0]); + &bpi_interior->extra->label[0]); } else prd = NULL; /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bi_interior->attr); - if (bi_exterior - && (bi_exterior->attr->flag + bgp_attr_dup(&new_attr, bpi_interior->attr); + if (bpi_exterior + && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { new_attr.local_pref = - bi_exterior->attr->local_pref; + bpi_exterior->attr->local_pref; new_attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF); } rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_UPDATE, bi_interior->peer, + it, FIF_ACTION_UPDATE, bpi_interior->peer, NULL, /* rfd */ pfx_exterior, NULL, afi, prd, &new_attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, @@ -2398,11 +2406,12 @@ void vnc_import_bgp_exterior_add_route_interior( } if (list_adopted) { struct listnode *node; - struct agg_node *an_bi_exterior; + struct agg_node *an_bpi_exterior; - for (ALL_LIST_ELEMENTS_RO(list_adopted, node, an_bi_exterior)) { + for (ALL_LIST_ELEMENTS_RO(list_adopted, node, + an_bpi_exterior)) { skiplist_delete(it->monitor_exterior_orphans, - an_bi_exterior, NULL); + an_bpi_exterior, NULL); } list_delete(&list_adopted); } @@ -2411,7 +2420,7 @@ void vnc_import_bgp_exterior_add_route_interior( /* * This function should be called after an interior VPN route * has been deleted from an import_table. - * bi_interior must still be valid, but it must already be detached + * bpi_interior must still be valid, but it must already be detached * from its route node and the route node's valid_interior_count * must already be decremented. * @@ -2420,20 +2429,20 @@ void vnc_import_bgp_exterior_add_route_interior( */ void vnc_import_bgp_exterior_del_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct agg_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior) /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_path_info *bpi_interior) /* VPN IT route */ { afi_t afi = family2afi(rn_interior->p.family); struct agg_node *par; - struct bgp_info *bi_exterior; + struct bgp_path_info *bpi_exterior; struct prefix *pfx_exterior; /* exterior pfx */ void *cursor; int rc; - if (!VALID_INTERIOR_TYPE(bi_interior->type)) { + if (!VALID_INTERIOR_TYPE(bpi_interior->type)) { vnc_zlog_debug_verbose( "%s: type %d not valid interior type, skipping", - __func__, bi_interior->type); + __func__, bpi_interior->type); return; } @@ -2462,8 +2471,8 @@ void vnc_import_bgp_exterior_del_route_interior( prefix2str(&rn_interior->p, str_pfx, sizeof(str_pfx)); - vnc_zlog_debug_verbose("%s: interior prefix=%s, bi type=%d", - __func__, str_pfx, bi_interior->type); + vnc_zlog_debug_verbose("%s: interior prefix=%s, bpi type=%d", + __func__, str_pfx, bpi_interior->type); } /* @@ -2471,25 +2480,25 @@ void vnc_import_bgp_exterior_del_route_interior( */ cursor = NULL; for (rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, (void **)&pfx_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor); !rc; rc = skiplist_next(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, (void **)&pfx_exterior, + (void **)&bpi_exterior, (void **)&pfx_exterior, &cursor)) { struct prefix_rd *prd; uint32_t label = 0; - if (bi_interior->extra) { - prd = &bi_interior->extra->vnc.import.rd; - label = decode_label(&bi_interior->extra->label[0]); + if (bpi_interior->extra) { + prd = &bpi_interior->extra->vnc.import.rd; + label = decode_label(&bpi_interior->extra->label[0]); } else prd = NULL; rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_KILL, bi_interior->peer, NULL, /* rfd */ - pfx_exterior, NULL, afi, prd, bi_interior->attr, + it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */ + pfx_exterior, NULL, afi, prd, bpi_interior->attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, BGP_ROUTE_REDISTRIBUTE, &label); } @@ -2524,7 +2533,8 @@ void vnc_import_bgp_exterior_del_route_interior( * We will use and delete every element of the source skiplist */ while (!skiplist_first(RFAPI_MONITOR_EXTERIOR(rn_interior)->source, - (void **)&bi_exterior, (void **)&pfx_exterior)) { + (void **)&bpi_exterior, + (void **)&pfx_exterior)) { struct prefix *pfx_mon = prefix_new(); @@ -2532,7 +2542,7 @@ void vnc_import_bgp_exterior_del_route_interior( if (par) { - struct bgp_info *bi; + struct bgp_path_info *bpi; /* * Add monitor to parent node @@ -2545,40 +2555,40 @@ void vnc_import_bgp_exterior_del_route_interior( agg_lock_node(par); /* sl */ } skiplist_insert(RFAPI_MONITOR_EXTERIOR(par)->source, - bi_exterior, pfx_mon); + bpi_exterior, pfx_mon); agg_lock_node(par); /* sl entry */ /* Add constructed exterior routes based on parent */ - for (bi = par->info; bi; bi = bi->next) { + for (bpi = par->info; bpi; bpi = bpi->next) { struct prefix_rd *prd; struct attr new_attr; uint32_t label = 0; - if (bi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) + if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT) continue; - if (bi->extra) { - prd = &bi->extra->vnc.import.rd; + if (bpi->extra) { + prd = &bpi->extra->vnc.import.rd; label = decode_label( - &bi->extra->label[0]); + &bpi->extra->label[0]); } else prd = NULL; /* use local_pref from unicast route */ memset(&new_attr, 0, sizeof(struct attr)); - bgp_attr_dup(&new_attr, bi->attr); - if (bi_exterior - && (bi_exterior->attr->flag + bgp_attr_dup(&new_attr, bpi->attr); + if (bpi_exterior + && (bpi_exterior->attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))) { new_attr.local_pref = - bi_exterior->attr->local_pref; + bpi_exterior->attr->local_pref; new_attr.flag |= ATTR_FLAG_BIT( BGP_ATTR_LOCAL_PREF); } rfapiBgpInfoFilteredImportVPN( - it, FIF_ACTION_UPDATE, bi->peer, + it, FIF_ACTION_UPDATE, bpi->peer, NULL, /* rfd */ pfx_exterior, NULL, afi, prd, &new_attr, ZEBRA_ROUTE_BGP_DIRECT_EXT, @@ -2593,7 +2603,7 @@ void vnc_import_bgp_exterior_del_route_interior( * in orphan list to await future route. */ skiplist_insert(it->monitor_exterior_orphans, - bi_exterior, pfx_mon); + bpi_exterior, pfx_mon); } skiplist_delete_first( @@ -2612,7 +2622,7 @@ void vnc_import_bgp_exterior_del_route_interior( ***********************************************************************/ void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info) + struct bgp_path_info *info) { afi_t afi = family2afi(prefix->family); @@ -2681,7 +2691,7 @@ void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix, * "Withdrawing a Route" import process */ void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info) /* unicast info */ + struct bgp_path_info *info) /* unicast info */ { afi_t afi = family2afi(prefix->family); @@ -2768,14 +2778,14 @@ void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi) for (rn = bgp_table_top(bgp->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; - vnc_import_bgp_add_route(bgp, &rn->p, bi); + vnc_import_bgp_add_route(bgp, &rn->p, bpi); } } vnc_zlog_debug_verbose( @@ -2808,15 +2818,15 @@ void vnc_import_bgp_exterior_redist_enable(struct bgp *bgp, afi_t afi) for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; vnc_import_bgp_exterior_add_route(bgp_exterior, &rn->p, - bi); + bpi); } } vnc_zlog_debug_verbose( @@ -2853,15 +2863,15 @@ void vnc_import_bgp_exterior_redist_enable_it( for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; vnc_import_bgp_exterior_add_route_it( - bgp_exterior, &rn->p, bi, it_only); + bgp_exterior, &rn->p, bpi, it_only); } } } @@ -2896,30 +2906,31 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) for (rn2 = bgp_table_top(rn1->info); rn2; rn2 = bgp_route_next(rn2)) { - struct bgp_info *bi; - struct bgp_info *nextbi; + struct bgp_path_info *bpi; + struct bgp_path_info *nextbpi; - for (bi = rn2->info; bi; bi = nextbi) { + for (bpi = rn2->info; bpi; bpi = nextbpi) { - nextbi = bi->next; + nextbpi = bpi->next; - if (bi->type + if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT) { struct rfapi_descriptor *rfd; - vncHDBgpDirect.peer = bi->peer; + vncHDBgpDirect.peer = bpi->peer; - assert(bi->extra); + assert(bpi->extra); - rfd = bi->extra->vnc.export + rfd = bpi->extra->vnc.export .rfapi_handle; vnc_zlog_debug_verbose( - "%s: deleting bi=%p, bi->peer=%p, bi->type=%d, bi->sub_type=%d, bi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]", - __func__, bi, bi->peer, - bi->type, bi->sub_type, - (bi->extra - ? bi->extra + "%s: deleting bpi=%p, bpi->peer=%p, bpi->type=%d, bpi->sub_type=%d, bpi->extra->vnc.export.rfapi_handle=%p [passing rfd=%p]", + __func__, bpi, + bpi->peer, bpi->type, + bpi->sub_type, + (bpi->extra + ? bpi->extra ->vnc .export .rfapi_handle @@ -2928,12 +2939,13 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) del_vnc_route( - rfd, bi->peer, bgp, + rfd, bpi->peer, bgp, SAFI_MPLS_VPN, &rn2->p, (struct prefix_rd *)&rn1 ->p, - bi->type, bi->sub_type, - NULL, 1); /* kill */ + bpi->type, + bpi->sub_type, NULL, + 1); /* kill */ vncHDBgpDirect.peer = NULL; } @@ -2944,12 +2956,12 @@ void vnc_import_bgp_redist_disable(struct bgp *bgp, afi_t afi) /* Clear RHN list */ if (bgp->rfapi->resolve_nve_nexthop) { struct prefix_bag *pb; - struct bgp_info *info; + struct bgp_path_info *info; while (!skiplist_first(bgp->rfapi->resolve_nve_nexthop, NULL, (void *)&pb)) { - info = pb->ubi; + info = pb->ubpi; skiplist_delete_first(bgp->rfapi->resolve_nve_nexthop); - bgp_info_unlock(info); + bgp_path_info_unlock(info); } } @@ -2985,15 +2997,15 @@ void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi) for (rn = bgp_table_top(bgp_exterior->rib[afi][SAFI_UNICAST]); rn; rn = bgp_route_next(rn)) { - struct bgp_info *bi; + struct bgp_path_info *bpi; - for (bi = rn->info; bi; bi = bi->next) { + for (bpi = rn->info; bpi; bpi = bpi->next) { - if (CHECK_FLAG(bi->flags, BGP_INFO_REMOVED)) + if (CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) continue; vnc_import_bgp_exterior_del_route(bgp_exterior, - &rn->p, bi); + &rn->p, bpi); } } #if DEBUG_RHN_LIST diff --git a/bgpd/rfapi/vnc_import_bgp.h b/bgpd/rfapi/vnc_import_bgp.h index 7c15939904..3db6f4010a 100644 --- a/bgpd/rfapi/vnc_import_bgp.h +++ b/bgpd/rfapi/vnc_import_bgp.h @@ -35,10 +35,10 @@ extern uint32_t calc_local_pref(struct attr *attr, struct peer *peer); extern int vnc_prefix_cmp(void *pfx1, void *pfx2); extern void vnc_import_bgp_add_route(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info); + struct bgp_path_info *info); extern void vnc_import_bgp_del_route(struct bgp *bgp, struct prefix *prefix, - struct bgp_info *info); + struct bgp_path_info *info); extern void vnc_import_bgp_redist_enable(struct bgp *bgp, afi_t afi); @@ -50,25 +50,24 @@ extern void vnc_import_bgp_exterior_redist_disable(struct bgp *bgp, afi_t afi); extern void vnc_import_bgp_exterior_add_route( - struct bgp *bgp, /* exterior instance, we hope */ - struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info); /* unicast info */ + struct bgp *bgp, /* exterior instance, we hope */ + struct prefix *prefix, /* unicast prefix */ + struct bgp_path_info *info); /* unicast info */ -extern void -vnc_import_bgp_exterior_del_route(struct bgp *bgp, - struct prefix *prefix, /* unicast prefix */ - struct bgp_info *info); /* unicast info */ +extern void vnc_import_bgp_exterior_del_route( + struct bgp *bgp, struct prefix *prefix, /* unicast prefix */ + struct bgp_path_info *info); /* unicast info */ extern void vnc_import_bgp_add_vnc_host_route_mode_resolve_nve( struct bgp *bgp, struct prefix_rd *prd, /* RD */ struct bgp_table *table_rd, /* per-rd VPN route table */ struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi); /* new VPN host route */ + struct bgp_path_info *bpi); /* new VPN host route */ extern void vnc_import_bgp_del_vnc_host_route_mode_resolve_nve( struct bgp *bgp, struct prefix_rd *prd, /* RD */ struct bgp_table *table_rd, /* per-rd VPN route table */ struct prefix *prefix, /* VPN prefix */ - struct bgp_info *bi); /* old VPN host route */ + struct bgp_path_info *bpi); /* old VPN host route */ #endif /* _QUAGGA_RFAPI_VNC_IMPORT_BGP_H_ */ diff --git a/bgpd/rfapi/vnc_import_bgp_p.h b/bgpd/rfapi/vnc_import_bgp_p.h index a6fcae926d..c6627dfba4 100644 --- a/bgpd/rfapi/vnc_import_bgp_p.h +++ b/bgpd/rfapi/vnc_import_bgp_p.h @@ -29,13 +29,13 @@ extern void vnc_import_bgp_exterior_add_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct agg_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_path_info *bpi_interior); /* VPN IT route */ extern void vnc_import_bgp_exterior_del_route_interior( struct bgp *bgp, struct rfapi_import_table *it, - struct agg_node *rn_interior, /* VPN IT node */ - struct bgp_info *bi_interior); /* VPN IT route */ + struct agg_node *rn_interior, /* VPN IT node */ + struct bgp_path_info *bpi_interior); /* VPN IT route */ extern void vnc_import_bgp_exterior_redist_enable_it(struct bgp *bgp, afi_t afi, diff --git a/bgpd/rfapi/vnc_zebra.c b/bgpd/rfapi/vnc_zebra.c index fdd200ac37..97d520eda7 100644 --- a/bgpd/rfapi/vnc_zebra.c +++ b/bgpd/rfapi/vnc_zebra.c @@ -313,10 +313,12 @@ 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)) { - struct bgp_info *ri; + struct bgp_path_info *ri; for (ri = rn->info; ri; ri = ri->next) { if (ri->type @@ -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/bgpd/rfp-example/rfptest/subdir.am b/bgpd/rfp-example/rfptest/subdir.am index fa7c660116..9f6d33a855 100644 --- a/bgpd/rfp-example/rfptest/subdir.am +++ b/bgpd/rfp-example/rfptest/subdir.am @@ -3,7 +3,7 @@ # if ENABLE_BGP_VNC -sbin_PROGRAMS += bgpd/rfp-example/rfptest/rfptest +noinst_PROGRAMS += bgpd/rfp-example/rfptest/rfptest endif bgpd_rfp_example_rfptest_rfptest_CFLAGS = -I$(top_srcdir)/bgpd/rfapi diff --git a/bgpd/subdir.am b/bgpd/subdir.am index 4291388567..83f55939ce 100644 --- a/bgpd/subdir.am +++ b/bgpd/subdir.am @@ -208,6 +208,8 @@ bgpd_bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS) bgpd_bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS) +bgpd/bgp_evpn_vty_clippy.c: $(CLIPPY_DEPS) +bgpd/bgp_evpn_vty.$(OBJEXT): bgpd/bgp_evpn_vty_clippy.c bgpd/bgp_vty_clippy.c: $(CLIPPY_DEPS) bgpd/bgp_vty.$(OBJEXT): bgpd/bgp_vty_clippy.c bgpd/bgp_route_clippy.c: $(CLIPPY_DEPS) diff --git a/config.version.in b/config.version.in new file mode 100644 index 0000000000..e2e739ca2d --- /dev/null +++ b/config.version.in @@ -0,0 +1,4 @@ +# this file is used to carry --with-pkg-extra-version into tarballs +EXTRAVERSION="@EXTRAVERSION@" +# for easy access by scripts before ./configure is run +DIST_PACKAGE_VERSION="@PACKAGE_VERSION@" diff --git a/configure.ac b/configure.ac index 12100121d6..706b954d6f 100755 --- a/configure.ac +++ b/configure.ac @@ -323,12 +323,48 @@ 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 ---------------------- +if test -f config.version; then + . ./config.version +elif test -f "${srcdir}/config.version"; then + . "${srcdir}/config.version" +fi AC_ARG_WITH(pkg-extra-version, - AS_HELP_STRING([--with-pkg-extra-version=VER], [add extra version field, for packagers/distributions]), - [EXTRAVERSION=$withval],) + AS_HELP_STRING([--with-pkg-extra-version=VER], [add extra version field, for packagers/distributions]), [ + if test "$withval" = "no"; then + EXTRAVERSION= + else + EXTRAVERSION=$withval + fi +], []) AC_ARG_WITH(pkg-git-version, AS_HELP_STRING([--with-pkg-git-version], [add git information to MOTD and build version string]), [ test "x$withval" != "xno" && with_pkg_git_version="yes" ]) @@ -462,9 +498,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 @@ -742,6 +778,7 @@ if test "x${EXTRAVERSION}" != "x" ; then AC_SUBST(PACKAGE_EXTRAVERSION, ["${EXTRAVERSION}"]) PACKAGE_STRING="${PACKAGE_STRING}${EXTRAVERSION}" fi +AC_SUBST(EXTRAVERSION) if test "x$with_pkg_git_version" = "xyes"; then if test -d "${srcdir}/.git"; then @@ -958,11 +995,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 +1060,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 +1441,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 +1501,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) @@ -1497,6 +1535,11 @@ if test "${enable_snmp}" != "" -a "${enable_snmp}" != "no"; then fi SNMP_LIBS="`${NETSNMP_CONFIG} --agent-libs`" SNMP_CFLAGS="`${NETSNMP_CONFIG} --base-cflags`" + # net-snmp lists all of its own dependencies. we absolutely do not want that + # among other things we avoid a GPL vs. OpenSSL license conflict here + for removelib in crypto ssl sensors pci wrap; do + SNMP_LIBS="`echo $SNMP_LIBS | sed -e 's/\(^\|\s\)-l'$removelib'\b/ /g' -e 's/\(^\|\s\)\([^\s]*\/\)\?lib'$removelib'\.[^\s]\+\b/ /g'`" + done AC_MSG_CHECKING([whether we can link to Net-SNMP]) AC_LINK_IFELSE_FLAGS([$SNMP_CFLAGS], [$SNMP_LIBS], [AC_LANG_PROGRAM([ int main(void); @@ -1811,17 +1854,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 @@ -2018,6 +2075,7 @@ AC_MSG_RESULT($ac_cv_htonl_works) AC_CONFIG_FILES([Makefile],[sed -e 's/^#AUTODERP# //' -i Makefile]) AC_CONFIG_FILES([ + config.version redhat/frr.spec solaris/Makefile debianpkg/changelog 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 Uploaders: Nobody XSBC-Original-Maintainer: -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/frr.logrotate b/debianpkg/frr.logrotate index 750b9aef13..1dc9122ac4 100644 --- a/debianpkg/frr.logrotate +++ b/debianpkg/frr.logrotate @@ -17,7 +17,7 @@ # open, as well as the daemons, so always signal the daemons. # It's safe, a NOP if (only) syslog is being used. for i in babeld bgpd eigrpd isisd ldpd nhrpd ospf6d ospfd \ - pimd ripd ripngd zebra staticd ; do + pimd ripd ripngd zebra staticd fabricd; do if [ -e /var/run/frr/$i.pid ] ; then pids="$pids $(cat /var/run/frr/$i.pid)" fi diff --git a/debianpkg/frr.manpages b/debianpkg/frr.manpages index d4bb920b46..f5aa972304 100644 --- a/debianpkg/frr.manpages +++ b/debianpkg/frr.manpages @@ -13,3 +13,4 @@ doc/manpages/_build/man/zebra.8 doc/manpages/_build/man/isisd.8 doc/manpages/_build/man/watchfrr.8 doc/manpages/_build/man/mtracebis.8 +doc/manpages/_build/man/fabricd.8 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/debianpkg/tests/daemons b/debianpkg/tests/daemons index ac35ecd950..43966c8347 100644 --- a/debianpkg/tests/daemons +++ b/debianpkg/tests/daemons @@ -6,7 +6,7 @@ set -e # modify config file to enable all daemons and copy config files CONFIG_FILE=/etc/frr/daemons -DAEMONS=("zebra" "bgpd" "ospfd" "ospf6d" "ripd" "ripngd" "isisd" "pimd") +DAEMONS=("zebra" "bgpd" "ospfd" "ospf6d" "ripd" "ripngd" "isisd" "pimd" "fabricd") for daemon in "${DAEMONS[@]}" do diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst index 5f10f3715d..f085598e08 100644 --- a/doc/developer/building-frr-for-centos6.rst +++ b/doc/developer/building-frr-for-centos6.rst @@ -44,8 +44,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk \ readline-devel texinfo net-snmp-devel groff pkgconfig \ - json-c-devel pam-devel flex epel-release perl-XML-LibXML \ - c-ares-devel + json-c-devel pam-devel flex epel-release c-ares-devel Install newer version of bison (CentOS 6 package source is too old) from CentOS 7: @@ -154,19 +153,12 @@ an example.) --disable-pimd \ --enable-snmp=agentx \ --enable-multipath=64 \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ - --enable-rtadv \ --disable-exampledir \ - --enable-watchfrr \ --disable-ldpd \ --enable-fpm \ - --enable-nhrpd \ - --enable-eigrpd \ - --enable-babeld \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion \ SPHINXBUILD=sphinx-build2.7 diff --git a/doc/developer/building-frr-for-centos7.rst b/doc/developer/building-frr-for-centos7.rst index b157f540ab..ca62b1239a 100644 --- a/doc/developer/building-frr-for-centos7.rst +++ b/doc/developer/building-frr-for-centos7.rst @@ -22,7 +22,7 @@ Add packages: sudo yum install git autoconf automake libtool make gawk \ readline-devel texinfo net-snmp-devel groff pkgconfig \ json-c-devel pam-devel bison flex pytest c-ares-devel \ - perl-XML-LibXML python-devel systemd-devel python-sphinx + python-devel systemd-devel python-sphinx Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -59,23 +59,15 @@ an example.) --libexecdir=/usr/lib/frr \ --localstatedir=/var/run/frr \ --with-moduledir=/usr/lib/frr/modules \ - --enable-pimd \ --enable-snmp=agentx \ --enable-multipath=64 \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ - --enable-rtadv \ --enable-systemd=yes \ --disable-exampledir \ - --enable-watchfrr \ --disable-ldpd \ --enable-fpm \ - --enable-nhrpd \ - --enable-eigrpd \ - --enable-babeld \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/developer/building-frr-for-debian8.rst b/doc/developer/building-frr-for-debian8.rst index d1e65a472d..2b591bf1aa 100644 --- a/doc/developer/building-frr-for-debian8.rst +++ b/doc/developer/building-frr-for-debian8.rst @@ -58,21 +58,13 @@ an example.) --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-vtysh \ - --enable-isisd \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/developer/building-frr-for-debian9.rst b/doc/developer/building-frr-for-debian9.rst index 7dad9a7bd4..db22e4f44e 100644 --- a/doc/developer/building-frr-for-debian9.rst +++ b/doc/developer/building-frr-for-debian9.rst @@ -39,28 +39,19 @@ an example.) git clone https://github.com/frrouting/frr.git frr cd frr - git checkout stable/3.0 ./bootstrap.sh ./configure \ --enable-exampledir=/usr/share/doc/frr/examples/ \ --localstatedir=/var/opt/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-vtysh \ - --enable-isisd \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/developer/building-frr-for-fedora24.rst b/doc/developer/building-frr-for-fedora24.rst index 669cc4ae2f..86e0c8d991 100644 --- a/doc/developer/building-frr-for-fedora24.rst +++ b/doc/developer/building-frr-for-fedora24.rst @@ -14,8 +14,8 @@ Add packages: sudo dnf install git autoconf automake libtool make gawk \ readline-devel texinfo net-snmp-devel groff pkgconfig \ - json-c-devel pam-devel perl-XML-LibXML pytest bison flex \ - c-ares-devel python3-devel python3-sphinx + json-c-devel pam-devel pytest bison flex c-ares-devel \ + python3-devel python3-sphinx Get FRR, compile it and install it (from Git) --------------------------------------------- @@ -52,22 +52,13 @@ an example.) --libexecdir=/usr/lib/frr \ --localstatedir=/var/run/frr \ --with-moduledir=/usr/lib/frr/modules \ - --enable-pimd \ --enable-snmp=agentx \ --enable-multipath=64 \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ - --enable-rtadv \ --disable-exampledir \ - --enable-watchfrr \ - --enable-ldpd \ --enable-fpm \ - --enable-nhrpd \ - --enable-eigrpd \ - --enable-babeld \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/developer/building-frr-for-freebsd10.rst b/doc/developer/building-frr-for-freebsd10.rst index 95f09e8c22..e9bc9adb16 100644 --- a/doc/developer/building-frr-for-freebsd10.rst +++ b/doc/developer/building-frr-for-freebsd10.rst @@ -59,15 +59,12 @@ an example) --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ --localstatedir=/var/run/frr \ --prefix=/usr/local \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-freebsd11.rst b/doc/developer/building-frr-for-freebsd11.rst index ce5941440c..f578f085ae 100644 --- a/doc/developer/building-frr-for-freebsd11.rst +++ b/doc/developer/building-frr-for-freebsd11.rst @@ -64,15 +64,12 @@ an example) --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ --localstatedir=/var/run/frr \ --prefix=/usr/local \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-freebsd9.rst b/doc/developer/building-frr-for-freebsd9.rst index 4f859d3510..0efa2ebd80 100644 --- a/doc/developer/building-frr-for-freebsd9.rst +++ b/doc/developer/building-frr-for-freebsd9.rst @@ -72,15 +72,12 @@ an example) --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ --localstatedir=/var/run/frr \ --prefix=/usr/local \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-netbsd6.rst b/doc/developer/building-frr-for-netbsd6.rst index ca0845d0d0..2023a4fafa 100644 --- a/doc/developer/building-frr-for-netbsd6.rst +++ b/doc/developer/building-frr-for-netbsd6.rst @@ -72,15 +72,12 @@ an example) --enable-exampledir=/usr/pkg/share/examples/frr \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ --localstatedir=/var/run/frr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-netbsd7.rst b/doc/developer/building-frr-for-netbsd7.rst index 86242ef965..6b31e68e8a 100644 --- a/doc/developer/building-frr-for-netbsd7.rst +++ b/doc/developer/building-frr-for-netbsd7.rst @@ -63,15 +63,12 @@ an example) --enable-exampledir=/usr/pkg/share/examples/frr \ --enable-pkgsrcrcdir=/usr/pkg/share/examples/rc.d \ --localstatedir=/var/run/frr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-omnios.rst b/doc/developer/building-frr-for-omnios.rst index 03f3845de8..45df049d39 100644 --- a/doc/developer/building-frr-for-omnios.rst +++ b/doc/developer/building-frr-for-omnios.rst @@ -119,17 +119,12 @@ an example) --enable-exampledir=/usr/share/doc/frr/examples/ \ --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ - --enable-vtysh \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-openbsd6.rst b/doc/developer/building-frr-for-openbsd6.rst index 46db25a025..c68c18eb7c 100644 --- a/doc/developer/building-frr-for-openbsd6.rst +++ b/doc/developer/building-frr-for-openbsd6.rst @@ -57,16 +57,12 @@ an example) ./configure \ --sysconfdir=/etc/frr \ --localstatedir=/var/frr \ - --enable-pimd \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=_frr \ --enable-group=_frr \ --enable-vty-group=_frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-ubuntu1204.rst b/doc/developer/building-frr-for-ubuntu1204.rst index 459d411ebc..1afd66c459 100644 --- a/doc/developer/building-frr-for-ubuntu1204.rst +++ b/doc/developer/building-frr-for-ubuntu1204.rst @@ -98,17 +98,12 @@ an example.) --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst index 681cc30a3b..98dbb79002 100644 --- a/doc/developer/building-frr-for-ubuntu1404.rst +++ b/doc/developer/building-frr-for-ubuntu1404.rst @@ -52,19 +52,13 @@ an example.) --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ - --enable-ldpd \ --with-pkg-git-version \ --with-pkg-extra-version=-MyOwnFRRVersion make diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst index 1fa0ede201..b2eec49236 100644 --- a/doc/developer/building-frr-for-ubuntu1604.rst +++ b/doc/developer/building-frr-for-ubuntu1604.rst @@ -53,17 +53,12 @@ an example.) --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --enable-systemd=yes \ --with-pkg-git-version \ diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst index 75b31a41f9..f5cf651e22 100644 --- a/doc/developer/building-frr-for-ubuntu1804.rst +++ b/doc/developer/building-frr-for-ubuntu1804.rst @@ -78,17 +78,12 @@ Options below are provided as an example. --localstatedir=/var/run/frr \ --sbindir=/usr/lib/frr \ --sysconfdir=/etc/frr \ - --enable-pimd \ - --enable-watchfrr \ - --enable-ospfclient=yes \ - --enable-ospfapi=yes \ --enable-multipath=64 \ --enable-user=frr \ --enable-group=frr \ --enable-vty-group=frrvty \ --enable-configfile-mask=0640 \ --enable-logfile-mask=0640 \ - --enable-rtadv \ --enable-fpm \ --enable-systemd=yes \ --with-pkg-git-version \ diff --git a/doc/developer/next-hop-tracking.rst b/doc/developer/next-hop-tracking.rst index 8a6a4ccb33..e6484102a8 100644 --- a/doc/developer/next-hop-tracking.rst +++ b/doc/developer/next-hop-tracking.rst @@ -241,7 +241,7 @@ Legend: /\ struct bgp_node: a BGP destination/route/prefix \/ - [ ] struct bgp_info: a BGP path (e.g. route received from a peer) + [ ] struct bgp_path_info: a BGP path (e.g. route received from a peer) _ (_) struct bgp_nexthop_cache: a BGP nexthop diff --git a/doc/manpages/common-options.rst b/doc/manpages/common-options.rst index 74d3eb7bbd..a5977a6ebb 100644 --- a/doc/manpages/common-options.rst +++ b/doc/manpages/common-options.rst @@ -136,7 +136,7 @@ These following options control the daemon's VTY (interactive command line) inte NB: Unlike the other options, this option specifies a directory, not a full path. - This option is primarily used by the SNAP packaging system, its semantics may change. It should not be neccessary in most other scenarios. + This option is primarily used by the SNAP packaging system, its semantics may change. It should not be necessary in most other scenarios. MODULE LOADING -------------- diff --git a/doc/manpages/subdir.am b/doc/manpages/subdir.am index 4a9aa4de4d..a4457c9c45 100644 --- a/doc/manpages/subdir.am +++ b/doc/manpages/subdir.am @@ -34,7 +34,8 @@ man_RSTFILES = \ EXTRA_DIST += $(man_RSTFILES) -MANBUILD = doc/manpages/_build/man +MANPARENT = doc/manpages/_build +MANBUILD = $(MANPARENT)/man doc/manpages/_build/.doctrees/environment.pickle: $(man_RSTFILES) # @@ -66,7 +67,7 @@ $(man8) $(man1): $(MANBUILD)/man.stamp clean-local: clean-manpages .PHONY: clean-manpages clean-manpages: - -rm -rf $(MANBUILD) + -rm -rf $(MANPARENT) doc: doc-man .PHONY: doc-man diff --git a/doc/manpages/zebra.rst b/doc/manpages/zebra.rst index a8a9301588..cfb368bf44 100644 --- a/doc/manpages/zebra.rst +++ b/doc/manpages/zebra.rst @@ -33,7 +33,7 @@ OPTIONS available for the |DAEMON| command: Set netlink receive buffer size. There are cases where zebra daemon can't handle flood of netlink messages from kernel. If you ever see "recvmsg overrun" messages in zebra log, you are in trouble. - Solution is to increase receive buffer of netlink socket. Note that kernel < 2.6.14 doesn't allow to increase it over maximum value defined in /proc/sys/net/core/rmem_max. If you want to do it, you have to increase maximum before starting zebra. + Solution is to increase receive buffer of netlink socket. Note that kernel < 2.6.14 doesn't allow increasing it over maximum value defined in /proc/sys/net/core/rmem_max. If you want to do it, you have to increase maximum before starting zebra. Note that this affects Linux only. diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst index f10883b984..a27243ea77 100644 --- a/doc/user/bgp.rst +++ b/doc/user/bgp.rst @@ -1171,7 +1171,7 @@ is 4 octet long. The following format is used to define the community value. ``0xFFFF0006`` ``65535:6``. Assigned and intented only for use with routers supporting the Long-lived Graceful Restart Capability as described in - :rfc:`draft-uttaro-idr-bgp-persistence`. + [Draft-IETF-uttaro-idr-bgp-persistence]_. Routers recieving routes with this community may (depending on implementation) choose allow to reject or modify routes on the presence or absence of this community. @@ -1181,7 +1181,7 @@ is 4 octet long. The following format is used to define the community value. ``0xFFFF0007`` ``65535:7``. Assigned and intented only for use with routers supporting the Long-lived Graceful Restart Capability as described in - :rfc:`draft-uttaro-idr-bgp-persistence`. + [Draft-IETF-uttaro-idr-bgp-persistence]_. Routers recieving routes with this community may (depending on implementation) choose allow to reject or modify routes on the presence or absence of this community. @@ -1189,10 +1189,10 @@ is 4 octet long. The following format is used to define the community value. ``accept-own-nexthop`` ``accept-own-nexthop`` represents well-known communities value ``accept-own-nexthop`` ``0xFFFF0008`` ``65535:8``. - :rfc:`draft-agrewal-idr-accept-own-nexthop` describes + [Draft-IETF-agrewal-idr-accept-own-nexthop]_ describes how to tag and label VPN routes to be able to send traffic between VRFs via an internal layer 2 domain on the same PE device. Refer to - :rfc:`draft-agrewal-idr-accept-own-nexthop` for full details. + [Draft-IETF-agrewal-idr-accept-own-nexthop]_ for full details. ``blackhole`` ``blackhole`` represents well-known communities value ``BLACKHOLE`` @@ -1230,6 +1230,9 @@ is 4 octet long. The following format is used to define the community value. When the communities attribute is received duplicate community values in the attribute are ignored and value is sorted in numerical order. +.. [Draft-IETF-uttaro-idr-bgp-persistence] +.. [Draft-IETF-agrewal-idr-accept-own-nexthop] + .. _bgp-community-lists: Community Lists @@ -1265,7 +1268,8 @@ expanded This command defines a new expanded community list. ``COMMUNITY`` is a string expression of communities attribute. ``COMMUNITY`` can be a regular expression (:ref:`bgp-regular-expressions`) to match the communities - attribute in BGP updates. + attribute in BGP updates. The expanded community is only used to filter, + not `set` actions. .. deprecated:: 5.0 It is recommended to use the more explicit versions of this command. @@ -1363,6 +1367,8 @@ The ollowing commands can be used in route maps: If ``none`` is specified as the community value, the communities attribute is not sent. + It is not possible to set an expanded community list. + .. index:: set comm-list WORD delete .. clicmd:: set comm-list WORD delete @@ -1603,6 +1609,10 @@ BGP Extended Communities in Route Map This command set Site of Origin value. + +Note that the extended expanded community is only used for `match` rule, not for +`set` actions. + .. _bgp-large-communities-attribute: Large Communities Attribute @@ -1714,6 +1724,8 @@ Large Communities in Route Map large-community list. The third will add a large-community value without overwriting other values. Multiple large-community values can be specified. +Note that the large expanded community is only used for `match` rule, not for +`set` actions. .. _bgp-l3vpn-vrfs: diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst index 57b4875e23..42a8250ae0 100644 --- a/doc/user/routemap.rst +++ b/doc/user/routemap.rst @@ -105,10 +105,10 @@ Route Map Match Command Matches the specified `access_list` -.. index:: match ip address PREFIX-LIST -.. clicmd:: match ip address PREFIX-LIST +.. index:: match ip address prefix-list PREFIX_LIST +.. clicmd:: match ip address prefix-list PREFIX_LIST - Matches the specified `prefix-list` + Matches the specified `PREFIX_LIST` .. index:: match ip address prefix-len 0-32 .. clicmd:: match ip address prefix-len 0-32 @@ -120,10 +120,10 @@ Route Map Match Command Matches the specified `access_list` -.. index:: match ipv6 address PREFIX-LIST -.. clicmd:: match ipv6 address PREFIX-LIST +.. index:: match ipv6 address prefix-list PREFIX_LIST +.. clicmd:: match ipv6 address prefix-list PREFIX_LIST - Matches the specified `prefix-list` + Matches the specified `PREFIX_LIST` .. index:: match ipv6 address prefix-len 0-128 .. clicmd:: match ipv6 address prefix-len 0-128 diff --git a/doc/user/subdir.am b/doc/user/subdir.am index 53d36052ac..08b5dc954c 100644 --- a/doc/user/subdir.am +++ b/doc/user/subdir.am @@ -100,12 +100,18 @@ uninstall-html: .PHONY: install-data-local uninstall-local if DOC DOC_INFO=info -install-data-local: install-info -uninstall-local: uninstall-info +TARGET_INSTALL_INFO=install-info +TARGET_UNINSTALL_INFO=uninstall-info endif if DOC_HTML DOC_HTML=html -install-data-local: install-html -uninstall-local: uninstall-html +TARGET_INSTALL_HTML=install-html +TARGET_UNINSTALL_HTML=uninstall-html endif + +# leave the comments in, this was causing weird reordering issues in automake +install-data-local: $(TARGET_INSTALL_INFO) $(TARGET_INSTALL_HTML) +# +uninstall-local: $(TARGET_UNINSTALL_INFO) $(TARGET_UNINSTALL_HTML) +# doc: $(DOC_INFO) $(DOC_HTML) diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst index e3e5d1325a..1cfb7953d4 100644 --- a/doc/user/zebra.rst +++ b/doc/user/zebra.rst @@ -186,6 +186,8 @@ Standard Commands Enable/disable link-detect on platforms which support this. Currently only Linux and Solaris, and only where network interface drivers support reporting link-state via the ``IFF_RUNNING`` flag. + + In FRR, link-detect is on by default. .. _link-parameters-commands: diff --git a/eigrpd/eigrp_const.h b/eigrpd/eigrp_const.h index 3d84c82179..895a141e4a 100644 --- a/eigrpd/eigrp_const.h +++ b/eigrpd/eigrp_const.h @@ -152,7 +152,7 @@ enum eigrp_fsm_states { enum eigrp_fsm_events { /* * Input event other than query from succ, - * FC is not satisified + * FC is not satisfied */ EIGRP_FSM_EVENT_NQ_FCN, @@ -171,7 +171,7 @@ enum eigrp_fsm_events { /* Query from succ while in active state */ EIGRP_FSM_EVENT_QACT, - /* last reply, FC not satisified */ + /* last reply, FC not satisfied */ EIGRP_FSM_EVENT_LR_FCN, /* diff --git a/eigrpd/eigrp_dump.c b/eigrpd/eigrp_dump.c index bbe2b88223..27e02630a6 100644 --- a/eigrpd/eigrp_dump.c +++ b/eigrpd/eigrp_dump.c @@ -228,7 +228,7 @@ void show_ip_eigrp_interface_detail(struct vty *vty, struct eigrp *eigrp, "Un/reliable mcasts: ", 0, "/", 0, "Un/reliable ucasts: ", 0, "/", 0); vty_out(vty, "%-2s %s %d %s %d %s %d \n", "", "Mcast exceptions: ", 0, - " CR packets: ", 0, " ACKs supressed: ", 0); + " CR packets: ", 0, " ACKs suppressed: ", 0); vty_out(vty, "%-2s %s %d %s %d \n", "", "Retransmissions sent: ", 0, "Out-of-sequence rcvd: ", 0); vty_out(vty, "%-2s %s %s %s \n", "", "Authentication mode is ", "not", diff --git a/eigrpd/eigrp_fsm.c b/eigrpd/eigrp_fsm.c index f955e6df0f..374114cf55 100644 --- a/eigrpd/eigrp_fsm.c +++ b/eigrpd/eigrp_fsm.c @@ -222,9 +222,9 @@ static const char *fsm_state2str(enum eigrp_fsm_events event) case EIGRP_FSM_EVENT_LR: return "Last Reply Event"; case EIGRP_FSM_EVENT_Q_FCN: - return "Query Event Feasability not satisified"; + return "Query Event Feasability not satisfied"; case EIGRP_FSM_EVENT_LR_FCS: - return "Last Reply Event Feasability satisified"; + return "Last Reply Event Feasability satisfied"; case EIGRP_FSM_EVENT_DINC: return "Distance Increase Event"; case EIGRP_FSM_EVENT_QACT: diff --git a/eigrpd/eigrp_vty.c b/eigrpd/eigrp_vty.c index 311fbce4ab..a0c4fa887a 100644 --- a/eigrpd/eigrp_vty.c +++ b/eigrpd/eigrp_vty.c @@ -55,6 +55,10 @@ #include "eigrpd/eigrp_dump.h" #include "eigrpd/eigrp_const.h" +#ifndef VTYSH_EXTRACT_PL +#include "eigrpd/eigrp_vty_clippy.c" +#endif + static int config_write_network(struct vty *vty, struct eigrp *eigrp) { struct route_node *rn; @@ -657,16 +661,15 @@ DEFUN (no_eigrp_if_delay, return CMD_SUCCESS; } -DEFUN (eigrp_if_bandwidth, +DEFPY (eigrp_if_bandwidth, eigrp_if_bandwidth_cmd, - "eigrp bandwidth (1-10000000)", + "eigrp bandwidth (1-10000000)$bw", "EIGRP specific commands\n" "Set bandwidth informational parameter\n" "Bandwidth in kilobits\n") { VTY_DECLVAR_CONTEXT(interface, ifp); struct eigrp_interface *ei = ifp->info; - uint32_t bandwidth; struct eigrp *eigrp; eigrp = eigrp_lookup(); @@ -680,9 +683,7 @@ DEFUN (eigrp_if_bandwidth, return CMD_SUCCESS; } - bandwidth = atoi(argv[1]->arg); - - ei->params.bandwidth = bandwidth; + ei->params.bandwidth = bw; eigrp_if_reset(ifp); return CMD_SUCCESS; @@ -975,9 +976,10 @@ DEFUN (no_eigrp_authentication_mode, return CMD_SUCCESS; } -DEFUN (eigrp_authentication_keychain, +DEFPY (eigrp_authentication_keychain, eigrp_authentication_keychain_cmd, - "ip authentication key-chain eigrp (1-65535) WORD", + "[no] ip authentication key-chain eigrp (1-65535)$as WORD$name", + NO_STR "Interface Internet Protocol config commands\n" "Authentication subcommands\n" "Key-chain\n" @@ -1001,52 +1003,29 @@ DEFUN (eigrp_authentication_keychain, return CMD_SUCCESS; } - keychain = keychain_lookup(argv[4]->arg); + if (no) { + if ((ei->params.auth_keychain != NULL) + && (strcmp(ei->params.auth_keychain, name) == 0)) { + free(ei->params.auth_keychain); + ei->params.auth_keychain = NULL; + } else + vty_out(vty, + "Key chain with specified name not configured on interface\n"); + return CMD_SUCCESS; + } + + keychain = keychain_lookup(name); if (keychain != NULL) { if (ei->params.auth_keychain) { free(ei->params.auth_keychain); ei->params.auth_keychain = strdup(keychain->name); } else ei->params.auth_keychain = strdup(keychain->name); - } else - vty_out(vty, "Key chain with specified name not found\n"); - - return CMD_SUCCESS; -} - -DEFUN (no_eigrp_authentication_keychain, - no_eigrp_authentication_keychain_cmd, - "no ip authentication key-chain eigrp (1-65535) WORD", - "Disable\n" - "Interface Internet Protocol config commands\n" - "Authentication subcommands\n" - "Key-chain\n" - "Enhanced Interior Gateway Routing Protocol (EIGRP)\n" - "Autonomous system number\n" - "Name of key-chain\n") -{ - VTY_DECLVAR_CONTEXT(interface, ifp); - struct eigrp_interface *ei = ifp->info; - struct eigrp *eigrp; - - eigrp = eigrp_lookup(); - if (eigrp == NULL) { - vty_out(vty, "EIGRP Routing Process not enabled\n"); - return CMD_SUCCESS; - } - - if (!ei) { - vty_out(vty, " EIGRP not configured on this interface\n"); - return CMD_SUCCESS; - } - - if ((ei->params.auth_keychain != NULL) - && (strcmp(ei->params.auth_keychain, argv[5]->arg) == 0)) { - free(ei->params.auth_keychain); - ei->params.auth_keychain = NULL; - } else + } else { vty_out(vty, - "Key chain with specified name not configured on interface\n"); + "Key chain with specified name not found\n"); + return CMD_WARNING_CONFIG_FAILED; + } return CMD_SUCCESS; } @@ -1538,7 +1517,6 @@ void eigrp_vty_if_init(void) install_element(INTERFACE_NODE, &eigrp_authentication_mode_cmd); install_element(INTERFACE_NODE, &no_eigrp_authentication_mode_cmd); install_element(INTERFACE_NODE, &eigrp_authentication_keychain_cmd); - install_element(INTERFACE_NODE, &no_eigrp_authentication_keychain_cmd); /*EIGRP Summarization commands*/ install_element(INTERFACE_NODE, &eigrp_ip_summary_address_cmd); diff --git a/eigrpd/subdir.am b/eigrpd/subdir.am index bc48173bba..86061b3ae3 100644 --- a/eigrpd/subdir.am +++ b/eigrpd/subdir.am @@ -44,6 +44,9 @@ eigrpdheader_HEADERS = \ eigrpd/eigrpd.h \ # end +eigrpd/eigrp_vty_clippy.c: $(CLIPPY_DEPS) +eigrpd/eigrp_vty.$(OBJEXT): eigrpd/eigrp_vty_clippy.c + noinst_HEADERS += \ eigrpd/eigrp_const.h \ eigrpd/eigrp_errors.h \ diff --git a/gdb/lib.txt b/gdb/lib.txt index b703808b48..60a004e1e1 100644 --- a/gdb/lib.txt +++ b/gdb/lib.txt @@ -16,7 +16,7 @@ # ... # (gdb) cont # Breakpoint 3, bgp_write_packet (peer=0x7fa885199080) at bgp_packet.c:614 -# 614 if (CHECK_FLAG (adv->binfo->peer->cap,PEER_CAP_RESTART_RCV) +# 614 if (CHECK_FLAG (adv->path->peer->cap,PEER_CAP_RESTART_RCV) # (gdb) dump_prefix4 &adv->rn->p # IPv4:10.1.1.0/24 # (gdb) dump_prefix &adv->rn->p 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_adjacency.c b/isisd/isis_adjacency.c index a41d6ff815..9013c7c19b 100644 --- a/isisd/isis_adjacency.c +++ b/isisd/isis_adjacency.c @@ -122,6 +122,8 @@ struct isis_adjacency *isis_adj_lookup_snpa(const uint8_t *ssnpa, return NULL; } +DEFINE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj)) + void isis_delete_adj(void *arg) { struct isis_adjacency *adj = arg; @@ -130,6 +132,10 @@ void isis_delete_adj(void *arg) return; THREAD_TIMER_OFF(adj->t_expire); + if (adj->adj_state != ISIS_ADJ_DOWN) { + adj->adj_state = ISIS_ADJ_DOWN; + hook_call(isis_adj_state_change_hook, adj); + } /* remove from SPF trees */ spftree_area_adj_del(adj->circuit->area, adj); @@ -256,8 +262,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; - isis_event_adjacency_state_change(adj, - new_state); + hook_call(isis_adj_state_change_hook, adj); /* update counter & timers for debugging * purposes */ adj->last_flap = time(NULL); @@ -270,8 +275,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, if (circuit->upadjcount[level - 1] == 0) isis_tx_queue_clean(circuit->tx_queue); - isis_event_adjacency_state_change(adj, - new_state); + hook_call(isis_adj_state_change_hook, adj); del = true; } @@ -299,8 +303,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, continue; if (new_state == ISIS_ADJ_UP) { circuit->upadjcount[level - 1]++; - isis_event_adjacency_state_change(adj, - new_state); + hook_call(isis_adj_state_change_hook, adj); if (adj->sys_type == ISIS_SYSTYPE_UNKNOWN) send_hello(circuit, level); @@ -326,8 +329,7 @@ void isis_adj_state_change(struct isis_adjacency *adj, if (circuit->upadjcount[level - 1] == 0) isis_tx_queue_clean(circuit->tx_queue); - isis_event_adjacency_state_change(adj, - new_state); + hook_call(isis_adj_state_change_hook, adj); del = true; } } diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h index 2f39378c00..2a4cb6e614 100644 --- a/isisd/isis_adjacency.h +++ b/isisd/isis_adjacency.h @@ -68,6 +68,8 @@ struct isis_dis_record { time_t last_dis_change; /* timestamp for last dis change */ }; +struct bfd_session; + struct isis_adjacency { uint8_t snpa[ETH_ALEN]; /* NeighbourSNPAAddress */ uint8_t sysid[ISIS_SYS_ID_LEN]; /* neighbourSystemIdentifier */ @@ -100,6 +102,7 @@ struct isis_adjacency { struct isis_circuit *circuit; /* back pointer */ uint16_t *mt_set; /* Topologies this adjacency is valid for */ unsigned int mt_count; /* Number of entries in mt_set */ + struct bfd_session *bfd_session; }; struct isis_threeway_adj; @@ -114,6 +117,7 @@ void isis_delete_adj(void *adj); void isis_adj_process_threeway(struct isis_adjacency *adj, struct isis_threeway_adj *tw_adj, enum isis_adj_usage adj_usage); +DECLARE_HOOK(isis_adj_state_change_hook, (struct isis_adjacency *adj), (adj)) void isis_adj_state_change(struct isis_adjacency *adj, enum isis_adj_state state, const char *reason); void isis_adj_print(struct isis_adjacency *adj); diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c new file mode 100644 index 0000000000..81976f8dd2 --- /dev/null +++ b/isisd/isis_bfd.c @@ -0,0 +1,350 @@ +/* + * IS-IS Rout(e)ing protocol - BFD support + * Copyright (C) 2018 Christian Franke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "zclient.h" +#include "bfd.h" + +#include "isisd/isis_bfd.h" +#include "isisd/isis_zebra.h" +#include "isisd/isis_common.h" +#include "isisd/isis_constants.h" +#include "isisd/isis_adjacency.h" +#include "isisd/isis_circuit.h" +#include "isisd/isisd.h" +#include "isisd/fabricd.h" + +DEFINE_MTYPE_STATIC(ISISD, BFD_SESSION, "ISIS BFD Session") + +struct bfd_session { + struct in_addr dst_ip; + struct in_addr src_ip; + int status; +}; + +static struct bfd_session *bfd_session_new(struct in_addr *dst_ip, + struct in_addr *src_ip) +{ + struct bfd_session *rv; + + rv = XCALLOC(MTYPE_BFD_SESSION, sizeof(*rv)); + rv->dst_ip = *dst_ip; + rv->src_ip = *src_ip; + return rv; +} + +static void bfd_session_free(struct bfd_session **session) +{ + if (!*session) + return; + + XFREE(MTYPE_BFD_SESSION, *session); + *session = NULL; +} + +static void bfd_adj_event(struct isis_adjacency *adj, struct prefix *dst, + int new_status) +{ + if (!adj->bfd_session) + return; + + if (adj->bfd_session->dst_ip.s_addr != dst->u.prefix4.s_addr) + return; + + int old_status = adj->bfd_session->status; + + adj->bfd_session->status = new_status; + if (old_status == new_status) + return; + + if (isis->debugs & DEBUG_BFD) { + char dst_str[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET, &adj->bfd_session->dst_ip, + dst_str, sizeof(dst_str)); + zlog_debug("ISIS-BFD: Peer %s on %s changed from %s to %s", + dst_str, adj->circuit->interface->name, + bfd_get_status_str(old_status), + bfd_get_status_str(new_status)); + } + + if (old_status != BFD_STATUS_UP + || new_status != BFD_STATUS_DOWN) { + return; + } + + isis_adj_state_change(adj, ISIS_ADJ_DOWN, "bfd session went down"); +} + +static int isis_bfd_interface_dest_update(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + struct interface *ifp; + struct prefix dst_ip; + int status; + + ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, vrf_id); + if (!ifp || dst_ip.family != AF_INET) + return 0; + + if (isis->debugs & DEBUG_BFD) { + char dst_buf[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET, &dst_ip.u.prefix4, + dst_buf, sizeof(dst_buf)); + + zlog_debug("ISIS-BFD: Received update for %s on %s: Changed state to %s", + dst_buf, ifp->name, bfd_get_status_str(status)); + } + + struct isis_circuit *circuit = circuit_scan_by_ifp(ifp); + + if (!circuit) + return 0; + + if (circuit->circ_type == CIRCUIT_T_BROADCAST) { + for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { + struct list *adjdb = circuit->u.bc.adjdb[level - 1]; + + struct listnode *node, *nnode; + struct isis_adjacency *adj; + + for (ALL_LIST_ELEMENTS(adjdb, node, nnode, adj)) + bfd_adj_event(adj, &dst_ip, status); + } + } else if (circuit->circ_type == CIRCUIT_T_P2P) { + if (circuit->u.p2p.neighbor) { + bfd_adj_event(circuit->u.p2p.neighbor, + &dst_ip, status); + } + } + + return 0; +} + +static int isis_bfd_nbr_replay(int command, struct zclient *zclient, + zebra_size_t length, vrf_id_t vrf_id) +{ + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); + + struct listnode *anode; + struct isis_area *area; + + if (isis->debugs & DEBUG_BFD) + zlog_debug("ISIS-BFD: Got neighbor replay request, resending neighbors."); + + for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) { + struct listnode *cnode; + struct isis_circuit *circuit; + + for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) + isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_UPDATE); + } + + if (isis->debugs & DEBUG_BFD) + zlog_debug("ISIS-BFD: Done with replay."); + + return 0; +} + +static void (*orig_zebra_connected)(struct zclient *); +static void isis_bfd_zebra_connected(struct zclient *zclient) +{ + if (orig_zebra_connected) + orig_zebra_connected(zclient); + + bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER); +} + +static void bfd_debug(struct in_addr *dst, struct in_addr *src, + const char *interface, int command) +{ + if (!(isis->debugs & DEBUG_BFD)) + return; + + char dst_str[INET6_ADDRSTRLEN]; + char src_str[INET6_ADDRSTRLEN]; + + inet_ntop(AF_INET, dst, dst_str, sizeof(dst_str)); + inet_ntop(AF_INET, src, src_str, sizeof(src_str)); + + const char *command_str; + + switch (command) { + case ZEBRA_BFD_DEST_REGISTER: + command_str = "Register"; + break; + case ZEBRA_BFD_DEST_DEREGISTER: + command_str = "Deregister"; + break; + case ZEBRA_BFD_DEST_UPDATE: + command_str = "Update"; + break; + default: + command_str = "Unknown-Cmd"; + break; + } + + zlog_debug("ISIS-BFD: %s peer %s on %s (src %s)", + command_str, dst_str, interface, src_str); +} + +static void bfd_handle_adj_down(struct isis_adjacency *adj) +{ + if (!adj->bfd_session) + return; + + bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, + adj->circuit->interface->name, ZEBRA_BFD_DEST_DEREGISTER); + + bfd_peer_sendmsg(zclient, NULL, AF_INET, + &adj->bfd_session->dst_ip, + &adj->bfd_session->src_ip, + adj->circuit->interface->name, + 0, /* ttl */ + 0, /* multihop */ + ZEBRA_BFD_DEST_DEREGISTER, + 0, /* set_flag */ + VRF_DEFAULT); + bfd_session_free(&adj->bfd_session); +} + +static void bfd_handle_adj_up(struct isis_adjacency *adj, int command) +{ + struct isis_circuit *circuit = adj->circuit; + + if (!circuit->bfd_info + || !circuit->ip_router + || !adj->ipv4_address_count) + goto out; + + struct list *local_ips = fabricd_ip_addrs(adj->circuit); + + if (!local_ips) + goto out; + + struct in_addr *dst_ip = &adj->ipv4_addresses[0]; + struct prefix_ipv4 *local_ip = listgetdata(listhead(local_ips)); + struct in_addr *src_ip = &local_ip->prefix; + + if (adj->bfd_session) { + if (adj->bfd_session->dst_ip.s_addr != dst_ip->s_addr + || adj->bfd_session->src_ip.s_addr != src_ip->s_addr) + bfd_handle_adj_down(adj); + } + + if (!adj->bfd_session) + adj->bfd_session = bfd_session_new(dst_ip, src_ip); + + bfd_debug(&adj->bfd_session->dst_ip, &adj->bfd_session->src_ip, + circuit->interface->name, command); + bfd_peer_sendmsg(zclient, circuit->bfd_info, AF_INET, + &adj->bfd_session->dst_ip, + &adj->bfd_session->src_ip, + circuit->interface->name, + 0, /* ttl */ + 0, /* multihop */ + command, + 0, /* set flag */ + VRF_DEFAULT); + return; +out: + bfd_handle_adj_down(adj); +} + +static int bfd_handle_adj_state_change(struct isis_adjacency *adj) +{ + if (adj->adj_state == ISIS_ADJ_UP) + bfd_handle_adj_up(adj, ZEBRA_BFD_DEST_REGISTER); + else + bfd_handle_adj_down(adj); + return 0; +} + +static void bfd_adj_cmd(struct isis_adjacency *adj, int command) +{ + if (adj->adj_state == ISIS_ADJ_UP + && command != ZEBRA_BFD_DEST_DEREGISTER) { + bfd_handle_adj_up(adj, command); + } else { + bfd_handle_adj_down(adj); + } +} + +void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command) +{ + switch (circuit->circ_type) { + case CIRCUIT_T_BROADCAST: + for (int level = ISIS_LEVEL1; level <= ISIS_LEVEL2; level++) { + struct list *adjdb = circuit->u.bc.adjdb[level - 1]; + + struct listnode *node; + struct isis_adjacency *adj; + + for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) + bfd_adj_cmd(adj, command); + } + break; + case CIRCUIT_T_P2P: + if (circuit->u.p2p.neighbor) + bfd_adj_cmd(circuit->u.p2p.neighbor, command); + break; + default: + break; + } +} + +void isis_bfd_circuit_param_set(struct isis_circuit *circuit, + uint32_t min_rx, uint32_t min_tx, + uint32_t detect_mult, int defaults) +{ + int command = 0; + + bfd_set_param(&circuit->bfd_info, min_rx, + min_tx, detect_mult, defaults, &command); + + if (command) + isis_bfd_circuit_cmd(circuit, command); +} + +static int bfd_circuit_write_settings(struct isis_circuit *circuit, + struct vty *vty) +{ + struct bfd_info *bfd_info = circuit->bfd_info; + + if (!bfd_info) + return 0; + + vty_out(vty, " %s bfd\n", PROTO_NAME); + return 1; +} + +void isis_bfd_init(void) +{ + bfd_gbl_init(); + + orig_zebra_connected = zclient->zebra_connected; + zclient->zebra_connected = isis_bfd_zebra_connected; + zclient->interface_bfd_dest_update = isis_bfd_interface_dest_update; + zclient->bfd_dest_replay = isis_bfd_nbr_replay; + hook_register(isis_adj_state_change_hook, + bfd_handle_adj_state_change); + hook_register(isis_circuit_config_write, + bfd_circuit_write_settings); +} diff --git a/isisd/isis_bfd.h b/isisd/isis_bfd.h new file mode 100644 index 0000000000..3193f16061 --- /dev/null +++ b/isisd/isis_bfd.h @@ -0,0 +1,31 @@ +/* + * IS-IS Rout(e)ing protocol - BFD support + * Copyright (C) 2018 Christian Franke + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef ISIS_BFD_H +#define ISIS_BFD_H + +struct isis_circuit; + +void isis_bfd_circuit_cmd(struct isis_circuit *circuit, int command); +void isis_bfd_circuit_param_set(struct isis_circuit *circuit, + uint32_t min_rx, uint32_t min_tx, + uint32_t detect_mult, int defaults); +void isis_bfd_init(void); + +#endif + diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c index 58c6dfa368..74488a1fcd 100644 --- a/isisd/isis_circuit.c +++ b/isisd/isis_circuit.c @@ -924,6 +924,10 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty, return; } +DEFINE_HOOK(isis_circuit_config_write, + (struct isis_circuit *circuit, struct vty *vty), + (circuit, vty)) + int isis_interface_config_write(struct vty *vty) { struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT); @@ -1138,7 +1142,8 @@ int isis_interface_config_write(struct vty *vty) circuit->passwd.passwd); write++; } - write += circuit_write_mt_settings(circuit, vty); + write += hook_call(isis_circuit_config_write, + circuit, vty); } vty_endframe(vty, "!\n"); } diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h index ea68767fe0..e83424a4ad 100644 --- a/isisd/isis_circuit.h +++ b/isisd/isis_circuit.h @@ -65,6 +65,8 @@ struct isis_p2p_info { struct thread *t_send_p2p_hello; /* send P2P IIHs in this thread */ }; +struct bfd_info; + struct isis_circuit { int state; uint8_t circuit_id; /* l1/l2 bcast CircuitID */ @@ -127,6 +129,7 @@ struct isis_circuit { #define ISIS_CIRCUIT_FLAPPED_AFTER_SPF 0x01 uint8_t flags; bool disable_threeway_adj; + struct bfd_info *bfd_info; /* * Counters as in 10589--11.2.5.9 */ @@ -190,4 +193,8 @@ ferr_r isis_circuit_passwd_hmac_md5_set(struct isis_circuit *circuit, int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid, bool enabled); +DECLARE_HOOK(isis_circuit_config_write, + (struct isis_circuit *circuit, struct vty *vty), + (circuit, vty)) + #endif /* _ZEBRA_ISIS_CIRCUIT_H */ diff --git a/isisd/isis_events.c b/isisd/isis_events.c index 5dcc0a1324..9f58c24b71 100644 --- a/isisd/isis_events.c +++ b/isisd/isis_events.c @@ -216,25 +216,6 @@ void isis_circuit_is_type_set(struct isis_circuit *circuit, int newtype) * * ***********************************************************************/ -void isis_event_adjacency_state_change(struct isis_adjacency *adj, int newstate) -{ - /* adjacency state change event. - * - the only proto-type was supported */ - - /* invalid arguments */ - if (!adj || !adj->circuit || !adj->circuit->area) - return; - - if (isis->debugs & DEBUG_EVENTS) - zlog_debug("ISIS-Evt (%s) Adjacency State change", - adj->circuit->area->area_tag); - - /* LSP generation again */ - lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); - - return; -} - /* events supporting code */ int isis_event_dis_status_change(struct thread *thread) diff --git a/isisd/isis_events.h b/isisd/isis_events.h index c3d8cf046f..25643f4ede 100644 --- a/isisd/isis_events.h +++ b/isisd/isis_events.h @@ -31,9 +31,6 @@ void isis_event_circuit_type_change(struct isis_circuit *circuit, int newtype); /* * Events related to adjacencies */ -void isis_event_adjacency_state_change(struct isis_adjacency *adj, - int newstate); - int isis_event_dis_status_change(struct thread *thread); /* diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c index 1258bec064..bb090f42ed 100644 --- a/isisd/isis_lsp.c +++ b/isisd/isis_lsp.c @@ -59,8 +59,7 @@ #include "isisd/fabricd.h" #include "isisd/isis_tx_queue.h" -static int lsp_l1_refresh(struct thread *thread); -static int lsp_l2_refresh(struct thread *thread); +static int lsp_refresh(struct thread *thread); static int lsp_l1_refresh_pseudo(struct thread *thread); static int lsp_l2_refresh_pseudo(struct thread *thread); @@ -110,6 +109,8 @@ static void lsp_clear_data(struct isis_lsp *lsp) lsp->tlvs = NULL; } +static void lsp_remove_frags(struct list *frags, dict_t *lspdb); + static void lsp_destroy(struct isis_lsp *lsp) { struct listnode *cnode; @@ -125,9 +126,17 @@ static void lsp_destroy(struct isis_lsp *lsp) lsp_clear_data(lsp); - if (LSP_FRAGMENT(lsp->hdr.lsp_id) == 0 && lsp->lspu.frags) { - list_delete(&lsp->lspu.frags); - lsp->lspu.frags = NULL; + if (!LSP_FRAGMENT(lsp->hdr.lsp_id)) { + if (lsp->lspu.frags) { + lsp_remove_frags(lsp->lspu.frags, + lsp->area->lspdb[lsp->level - 1]); + list_delete(&lsp->lspu.frags); + } + } else { + if (lsp->lspu.zero_lsp + && lsp->lspu.zero_lsp->lspu.frags) { + listnode_delete(lsp->lspu.zero_lsp->lspu.frags, lsp); + } } isis_spf_schedule(lsp->area, lsp->level); @@ -170,10 +179,6 @@ static void lsp_remove_frags(struct list *frags, dict_t *lspdb) lsp_destroy(lsp); dnode_destroy(dict_delete(lspdb, dnode)); } - - list_delete_all_node(frags); - - return; } void lsp_search_and_destroy(uint8_t *id, dict_t *lspdb) @@ -516,6 +521,17 @@ struct isis_lsp *lsp_new_from_recv(struct isis_lsp_hdr *hdr, return lsp; } +static void lsp_adjust_stream(struct isis_lsp *lsp) +{ + if (lsp->pdu) { + if (STREAM_SIZE(lsp->pdu) == LLC_LEN + lsp->area->lsp_mtu) + return; + stream_free(lsp->pdu); + } + + lsp->pdu = stream_new(LLC_LEN + lsp->area->lsp_mtu); +} + struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, uint16_t rem_lifetime, uint32_t seqno, uint8_t lsp_bits, uint16_t checksum, @@ -526,7 +542,7 @@ struct isis_lsp *lsp_new(struct isis_area *area, uint8_t *lsp_id, lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); lsp->area = area; - lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); + lsp_adjust_stream(lsp); /* Minimal LSP PDU size */ lsp->hdr.pdu_len = ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN; @@ -1147,6 +1163,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) struct isis_tlvs *tlvs = lsp->tlvs; lsp->tlvs = NULL; + lsp_adjust_stream(lsp); lsp_pack_pdu(lsp); size_t tlv_space = STREAM_WRITEABLE(lsp->pdu) - LLC_LEN; lsp_clear_data(lsp); @@ -1178,6 +1195,7 @@ static void lsp_build(struct isis_lsp *lsp, struct isis_area *area) frag = lsp_next_frag(LSP_FRAGMENT(frag->hdr.lsp_id) + 1, lsp, area, level); + lsp_adjust_stream(frag); } frag->tlvs = tlvs; } @@ -1232,12 +1250,9 @@ int lsp_generate(struct isis_area *area, int level) THREAD_TIMER_OFF(area->t_lsp_refresh[level - 1]); area->lsp_regenerate_pending[level - 1] = 0; - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); + thread_add_timer(master, lsp_refresh, + &area->lsp_refresh_arg[level - 1], refresh_time, + &area->t_lsp_refresh[level - 1]); if (isis->debugs & DEBUG_UPDATE_PACKETS) { zlog_debug("ISIS-Upd (%s): Building L%d LSP %s, len %" PRIu16 @@ -1304,12 +1319,9 @@ static int lsp_regenerate(struct isis_area *area, int level) lsp_seqno_update(lsp); refresh_time = lsp_refresh_time(lsp, rem_lifetime); - if (level == IS_LEVEL_1) - thread_add_timer(master, lsp_l1_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); - else if (level == IS_LEVEL_2) - thread_add_timer(master, lsp_l2_refresh, area, refresh_time, - &area->t_lsp_refresh[level - 1]); + thread_add_timer(master, lsp_refresh, + &area->lsp_refresh_arg[level - 1], refresh_time, + &area->t_lsp_refresh[level - 1]); area->lsp_regenerate_pending[level - 1] = 0; if (isis->debugs & DEBUG_UPDATE_PACKETS) { @@ -1331,45 +1343,42 @@ static int lsp_regenerate(struct isis_area *area, int level) /* * Something has changed or periodic refresh -> regenerate LSP */ -static int lsp_l1_refresh(struct thread *thread) +static int lsp_refresh(struct thread *thread) { - struct isis_area *area; + struct lsp_refresh_arg *arg = THREAD_ARG(thread); + + assert(arg); + + struct isis_area *area = arg->area; - area = THREAD_ARG(thread); assert(area); - area->t_lsp_refresh[0] = NULL; - area->lsp_regenerate_pending[0] = 0; + int level = arg->level; - if ((area->is_type & IS_LEVEL_1) == 0) + area->t_lsp_refresh[level - 1] = NULL; + area->lsp_regenerate_pending[level - 1] = 0; + + if ((area->is_type & level) == 0) return ISIS_ERROR; - sched_debug( - "ISIS (%s): LSP L1 refresh timer expired. Refreshing LSP...", - area->area_tag); - return lsp_regenerate(area, IS_LEVEL_1); -} - -static int lsp_l2_refresh(struct thread *thread) -{ - struct isis_area *area; - - area = THREAD_ARG(thread); - assert(area); - - area->t_lsp_refresh[1] = NULL; - area->lsp_regenerate_pending[1] = 0; - - if ((area->is_type & IS_LEVEL_2) == 0) - return ISIS_ERROR; + if (monotime_since(&area->last_lsp_refresh_event[level - 1], NULL) < 50000L) { + sched_debug("ISIS (%s): Still unstable, postpone LSP L%d refresh", + area->area_tag, level); + _lsp_regenerate_schedule(area, level, 0, false, + __func__, __FILE__, __LINE__); + return 0; + } sched_debug( - "ISIS (%s): LSP L2 refresh timer expired. Refreshing LSP...", - area->area_tag); - return lsp_regenerate(area, IS_LEVEL_2); + "ISIS (%s): LSP L%d refresh timer expired. Refreshing LSP...", + area->area_tag, level); + return lsp_regenerate(area, level); } -int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) +int _lsp_regenerate_schedule(struct isis_area *area, int level, + int all_pseudo, bool postpone, + const char *func, const char *file, + int line) { struct isis_lsp *lsp; uint8_t id[ISIS_SYS_ID_LEN + 2]; @@ -1383,9 +1392,11 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) return ISIS_ERROR; sched_debug( - "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs", + "ISIS (%s): Scheduling regeneration of %s LSPs, %sincluding PSNs" + " Caller: %s %s:%d", area->area_tag, circuit_t2string(level), - all_pseudo ? "" : "not "); + all_pseudo ? "" : "not ", + func, file, line); memcpy(id, isis->sysid, ISIS_SYS_ID_LEN); LSP_PSEUDO_ID(id) = LSP_FRAGMENT(id) = 0; @@ -1395,6 +1406,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) if (!((level & lvl) && (area->is_type & lvl))) continue; + if (postpone) { + monotime(&area->last_lsp_refresh_event[lvl - 1]); + } + sched_debug( "ISIS (%s): Checking whether L%d needs to be scheduled", area->area_tag, lvl); @@ -1449,15 +1464,10 @@ int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo) } area->lsp_regenerate_pending[lvl - 1] = 1; - if (lvl == IS_LEVEL_1) { - thread_add_timer_msec(master, lsp_l1_refresh, area, - timeout, - &area->t_lsp_refresh[lvl - 1]); - } else if (lvl == IS_LEVEL_2) { - thread_add_timer_msec(master, lsp_l2_refresh, area, - timeout, - &area->t_lsp_refresh[lvl - 1]); - } + thread_add_timer_msec(master, lsp_refresh, + &area->lsp_refresh_arg[lvl - 1], + timeout, + &area->t_lsp_refresh[lvl - 1]); } if (all_pseudo) { @@ -1950,7 +1960,7 @@ void lsp_purge_non_exist(int level, struct isis_lsp_hdr *hdr, lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp)); lsp->area = area; lsp->level = level; - lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu); + lsp_adjust_stream(lsp); lsp->age_out = ZERO_AGE_LIFETIME; memcpy(&lsp->hdr, hdr, sizeof(lsp->hdr)); @@ -1997,3 +2007,15 @@ void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit) fabricd_lsp_flood(lsp); } } + +static int lsp_handle_adj_state_change(struct isis_adjacency *adj) +{ + lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0); + return 0; +} + +void lsp_init(void) +{ + hook_register(isis_adj_state_change_hook, + lsp_handle_adj_state_change); +} diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h index 4e6379447c..2b45e6994c 100644 --- a/isisd/isis_lsp.h +++ b/isisd/isis_lsp.h @@ -54,7 +54,12 @@ void lsp_db_destroy(dict_t *lspdb); int lsp_tick(struct thread *thread); int lsp_generate(struct isis_area *area, int level); -int lsp_regenerate_schedule(struct isis_area *area, int level, int all_pseudo); +#define lsp_regenerate_schedule(area, level, all_pseudo) \ + _lsp_regenerate_schedule((area), (level), (all_pseudo), true, \ + __func__, __FILE__, __LINE__) +int _lsp_regenerate_schedule(struct isis_area *area, int level, + int all_pseudo, bool postpone, + const char *func, const char *file, int line); int lsp_generate_pseudo(struct isis_circuit *circuit, int level); int lsp_regenerate_schedule_pseudo(struct isis_circuit *circuit, int level); @@ -101,5 +106,6 @@ int lsp_print_all(struct vty *vty, dict_t *lspdb, char detail, char dynhost); /* sets SRMflags for all active circuits of an lsp */ void lsp_set_all_srmflags(struct isis_lsp *lsp, bool set); void lsp_flood(struct isis_lsp *lsp, struct isis_circuit *circuit); +void lsp_init(void); #endif /* ISIS_LSP */ diff --git a/isisd/isis_main.c b/isisd/isis_main.c index 4d6a6da5d6..7956ddeaf1 100644 --- a/isisd/isis_main.c +++ b/isisd/isis_main.c @@ -55,6 +55,9 @@ #include "isisd/isis_te.h" #include "isisd/isis_errors.h" #include "isisd/isis_vty_common.h" +#include "isisd/isis_bfd.h" +#include "isisd/isis_lsp.h" +#include "isisd/isis_mt.h" /* Default configuration file name */ #define ISISD_DEFAULT_CONFIG "isisd.conf" @@ -213,11 +216,14 @@ int main(int argc, char **argv, char **envp) isis_redist_init(); isis_route_map_init(); isis_mpls_te_init(); + lsp_init(); + mt_init(); /* create the global 'isis' instance */ isis_new(1); isis_zebra_init(master); + isis_bfd_init(); frr_config_fork(); frr_run(master); diff --git a/isisd/isis_mt.c b/isisd/isis_mt.c index e0227f4656..7493b90d33 100644 --- a/isisd/isis_mt.c +++ b/isisd/isis_mt.c @@ -302,7 +302,8 @@ circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid) return setting; } -int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty) +static int circuit_write_mt_settings(struct isis_circuit *circuit, + struct vty *vty) { int written = 0; struct listnode *node; @@ -551,3 +552,9 @@ void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit, tlvs_add_mt_set(circuit->area, tlvs, adj->mt_count, adj->mt_set, id, metric, subtlvs, subtlv_len); } + +void mt_init(void) +{ + hook_register(isis_circuit_config_write, + circuit_write_mt_settings); +} diff --git a/isisd/isis_mt.h b/isisd/isis_mt.h index 8c57d24afa..515b63f50f 100644 --- a/isisd/isis_mt.h +++ b/isisd/isis_mt.h @@ -109,7 +109,6 @@ void circuit_mt_init(struct isis_circuit *circuit); void circuit_mt_finish(struct isis_circuit *circuit); struct isis_circuit_mt_setting * circuit_get_mt_setting(struct isis_circuit *circuit, uint16_t mtid); -int circuit_write_mt_settings(struct isis_circuit *circuit, struct vty *vty); struct isis_circuit_mt_setting ** circuit_mt_settings(struct isis_circuit *circuit, unsigned int *mt_count); bool tlvs_to_adj_mt_set(struct isis_tlvs *tlvs, bool v4_usable, bool v6_usable, @@ -122,4 +121,5 @@ void tlvs_add_mt_bcast(struct isis_tlvs *tlvs, struct isis_circuit *circuit, void tlvs_add_mt_p2p(struct isis_tlvs *tlvs, struct isis_circuit *circuit, uint8_t *id, uint32_t metric, uint8_t *subtlvs, uint8_t subtlv_len); +void mt_init(void); #endif diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c index 1440a3becf..b6f751463a 100644 --- a/isisd/isis_spf.c +++ b/isisd/isis_spf.c @@ -887,7 +887,7 @@ static int isis_spf_preload_tent(struct isis_spftree *spftree, case ISIS_SYSTYPE_UNKNOWN: default: zlog_warn( - "isis_spf_preload_tent unknow adj type"); + "isis_spf_preload_tent unknown adj type"); } } list_delete(&adj_list); @@ -1248,7 +1248,8 @@ static struct isis_spf_run *isis_run_spf_arg(struct isis_area *area, int level) return run; } -int isis_spf_schedule(struct isis_area *area, int level) +int _isis_spf_schedule(struct isis_area *area, int level, + const char *func, const char *file, int line) { struct isis_spftree *spftree = area->spftree[SPFTREE_IPV4][level - 1]; time_t now = monotime(NULL); @@ -1257,10 +1258,12 @@ int isis_spf_schedule(struct isis_area *area, int level) assert(diff >= 0); assert(area->is_type & level); - if (isis->debugs & DEBUG_SPF_EVENTS) + if (isis->debugs & DEBUG_SPF_EVENTS) { zlog_debug( - "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago", - area->area_tag, level, diff); + "ISIS-Spf (%s) L%d SPF schedule called, lastrun %d sec ago" + " Caller: %s %s:%d", + area->area_tag, level, diff, func, file, line); + } if (area->spf_delay_ietf[level - 1]) { /* Need to call schedule function also if spf delay is running diff --git a/isisd/isis_spf.h b/isisd/isis_spf.h index f4db98cfed..8bf9c9978a 100644 --- a/isisd/isis_spf.h +++ b/isisd/isis_spf.h @@ -34,7 +34,11 @@ void isis_spftree_del(struct isis_spftree *spftree); void spftree_area_init(struct isis_area *area); void spftree_area_del(struct isis_area *area); void spftree_area_adj_del(struct isis_area *area, struct isis_adjacency *adj); -int isis_spf_schedule(struct isis_area *area, int level); +#define isis_spf_schedule(area, level) \ + _isis_spf_schedule((area), (level), __func__, \ + __FILE__, __LINE__) +int _isis_spf_schedule(struct isis_area *area, int level, + const char *func, const char *file, int line); void isis_spf_cmds_init(void); void isis_spf_print(struct isis_spftree *spftree, struct vty *vty); struct isis_spftree *isis_run_hopcount_spf(struct isis_area *area, 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/isisd/isis_vty_common.c b/isisd/isis_vty_common.c index 2b98a88b34..c211763042 100644 --- a/isisd/isis_vty_common.c +++ b/isisd/isis_vty_common.c @@ -28,12 +28,14 @@ #include "command.h" #include "spf_backoff.h" +#include "bfd.h" #include "isis_circuit.h" #include "isis_csm.h" #include "isis_misc.h" #include "isis_mt.h" #include "isisd.h" +#include "isis_bfd.h" #include "isis_vty_common.h" struct isis_circuit *isis_circuit_lookup(struct vty *vty) @@ -498,6 +500,49 @@ DEFUN (no_circuit_topology, return isis_circuit_mt_enabled_set(circuit, mtid, false); } +DEFUN (isis_bfd, + isis_bfd_cmd, + PROTO_NAME " bfd", + PROTO_HELP + "Enable BFD support\n") +{ + struct isis_circuit *circuit = isis_circuit_lookup(vty); + + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (circuit->bfd_info + && CHECK_FLAG(circuit->bfd_info->flags, BFD_FLAG_PARAM_CFG)) { + return CMD_SUCCESS; + } + + isis_bfd_circuit_param_set(circuit, BFD_DEF_MIN_RX, + BFD_DEF_MIN_TX, BFD_DEF_DETECT_MULT, true); + + return CMD_SUCCESS; +} + +DEFUN (no_isis_bfd, + no_isis_bfd_cmd, + "no " PROTO_NAME " bfd", + NO_STR + PROTO_HELP + "Disables BFD support\n" +) +{ + struct isis_circuit *circuit = isis_circuit_lookup(vty); + + if (!circuit) + return CMD_ERR_NO_MATCH; + + if (!circuit->bfd_info) + return CMD_SUCCESS; + + isis_bfd_circuit_cmd(circuit, ZEBRA_BFD_DEST_DEREGISTER); + bfd_info_free(&circuit->bfd_info); + return CMD_SUCCESS; +} + DEFUN (set_overload_bit, set_overload_bit_cmd, "set-overload-bit", @@ -930,6 +975,9 @@ void isis_vty_init(void) install_element(INTERFACE_NODE, &circuit_topology_cmd); install_element(INTERFACE_NODE, &no_circuit_topology_cmd); + install_element(INTERFACE_NODE, &isis_bfd_cmd); + install_element(INTERFACE_NODE, &no_isis_bfd_cmd); + install_element(ROUTER_NODE, &set_overload_bit_cmd); install_element(ROUTER_NODE, &no_set_overload_bit_cmd); diff --git a/isisd/isis_zebra.h b/isisd/isis_zebra.h index 4fbcf87217..20c10d0b23 100644 --- a/isisd/isis_zebra.h +++ b/isisd/isis_zebra.h @@ -27,6 +27,8 @@ extern struct zclient *zclient; void isis_zebra_init(struct thread_master *); void isis_zebra_stop(void); +struct isis_route_info; + void isis_zebra_route_update(struct prefix *prefix, struct prefix_ipv6 *src_p, struct isis_route_info *route_info); diff --git a/isisd/isisd.c b/isisd/isisd.c index e5e43c4b7d..54bdbf3eb3 100644 --- a/isisd/isisd.c +++ b/isisd/isisd.c @@ -160,6 +160,13 @@ struct isis_area *isis_area_create(const char *area_tag) if (fabricd) area->fabricd = fabricd_new(area); + + area->lsp_refresh_arg[0].area = area; + area->lsp_refresh_arg[0].level = IS_LEVEL_1; + area->lsp_refresh_arg[1].area = area; + area->lsp_refresh_arg[1].level = IS_LEVEL_2; + + QOBJ_REG(area, isis_area); return area; @@ -746,6 +753,8 @@ void print_debug(struct vty *vty, int flags, int onoff) vty_out(vty, "IS-IS LSP scheduling debugging is %s\n", onoffs); if (flags & DEBUG_FABRICD_FLOODING) vty_out(vty, "OpenFabric Flooding debugging is %s\n", onoffs); + if (flags & DEBUG_BFD) + vty_out(vty, "IS-IS BFD debugging is %s\n", onoffs); } DEFUN_NOSH (show_debugging, @@ -831,6 +840,10 @@ static int config_write_debug(struct vty *vty) vty_out(vty, "debug " PROTO_NAME " flooding\n"); write++; } + if (flags & DEBUG_BFD) { + vty_out(vty, "debug " PROTO_NAME " bfd\n"); + write++; + } write += spf_backoff_write_config(vty); return write; @@ -1214,6 +1227,33 @@ DEFUN (no_debug_isis_lsp_sched, return CMD_SUCCESS; } +DEFUN (debug_isis_bfd, + debug_isis_bfd_cmd, + "debug " PROTO_NAME " bfd", + DEBUG_STR + PROTO_HELP + PROTO_NAME " interaction with BFD\n") +{ + isis->debugs |= DEBUG_BFD; + print_debug(vty, DEBUG_BFD, 1); + + return CMD_SUCCESS; +} + +DEFUN (no_debug_isis_bfd, + no_debug_isis_bfd_cmd, + "no debug " PROTO_NAME " bfd", + NO_STR + UNDEBUG_STR + PROTO_HELP + PROTO_NAME " interaction with BFD\n") +{ + isis->debugs &= ~DEBUG_BFD; + print_debug(vty, DEBUG_BFD, 0); + + return CMD_SUCCESS; +} + DEFUN (show_hostname, show_hostname_cmd, "show " PROTO_NAME " hostname", @@ -2215,6 +2255,8 @@ void isis_init() install_element(ENABLE_NODE, &no_debug_isis_lsp_gen_cmd); install_element(ENABLE_NODE, &debug_isis_lsp_sched_cmd); install_element(ENABLE_NODE, &no_debug_isis_lsp_sched_cmd); + install_element(ENABLE_NODE, &debug_isis_bfd_cmd); + install_element(ENABLE_NODE, &no_debug_isis_bfd_cmd); install_element(CONFIG_NODE, &debug_isis_adj_cmd); install_element(CONFIG_NODE, &no_debug_isis_adj_cmd); @@ -2244,6 +2286,8 @@ void isis_init() install_element(CONFIG_NODE, &no_debug_isis_lsp_gen_cmd); install_element(CONFIG_NODE, &debug_isis_lsp_sched_cmd); install_element(CONFIG_NODE, &no_debug_isis_lsp_sched_cmd); + install_element(CONFIG_NODE, &debug_isis_bfd_cmd); + install_element(CONFIG_NODE, &no_debug_isis_bfd_cmd); install_element(CONFIG_NODE, &router_isis_cmd); install_element(CONFIG_NODE, &no_router_isis_cmd); diff --git a/isisd/isisd.h b/isisd/isisd.h index 864021428a..51b359aad4 100644 --- a/isisd/isisd.h +++ b/isisd/isisd.h @@ -90,6 +90,11 @@ enum spf_tree_id { SPFTREE_COUNT }; +struct lsp_refresh_arg { + struct isis_area *area; + int level; +}; + struct isis_area { struct isis *isis; /* back pointer */ dict_t *lspdb[ISIS_LEVELS]; /* link-state dbs */ @@ -100,6 +105,7 @@ struct isis_area { struct flags flags; struct thread *t_tick; /* LSP walker */ struct thread *t_lsp_refresh[ISIS_LEVELS]; + struct timeval last_lsp_refresh_event[ISIS_LEVELS]; /* t_lsp_refresh is used in two ways: * a) regular refresh of LSPs * b) (possibly throttled) updates to LSPs @@ -160,6 +166,8 @@ struct isis_area { parameters*/ struct thread *spf_timer[ISIS_LEVELS]; + struct lsp_refresh_arg lsp_refresh_arg[ISIS_LEVELS]; + QOBJ_FIELDS }; DECLARE_QOBJ_TYPE(isis_area) @@ -211,6 +219,7 @@ extern struct thread_master *master; #define DEBUG_LSP_GEN (1<<13) #define DEBUG_LSP_SCHED (1<<14) #define DEBUG_FABRICD_FLOODING (1<<15) +#define DEBUG_BFD (1<<16) #define lsp_debug(...) \ do { \ diff --git a/isisd/subdir.am b/isisd/subdir.am index 7571255e59..552bc49b80 100644 --- a/isisd/subdir.am +++ b/isisd/subdir.am @@ -27,6 +27,7 @@ endif noinst_HEADERS += \ isisd/dict.h \ isisd/isis_adjacency.h \ + isisd/isis_bfd.h \ isisd/isis_circuit.h \ isisd/isis_common.h \ isisd/isis_constants.h \ @@ -60,6 +61,7 @@ noinst_HEADERS += \ LIBISIS_SOURCES = \ isisd/dict.c \ isisd/isis_adjacency.c \ + isisd/isis_bfd.c \ isisd/isis_circuit.c \ isisd/isis_csm.c \ isisd/isis_dr.c \ diff --git a/ldpd/ldp_vty_cmds.c b/ldpd/ldp_vty_cmds.c index 8eed089900..c24e1917cc 100644 --- a/ldpd/ldp_vty_cmds.c +++ b/ldpd/ldp_vty_cmds.c @@ -156,7 +156,7 @@ DEFPY (ldp_dual_stack_transport_connection_prefer_ipv4, NO_STR "Configure dual stack parameters\n" "Configure TCP transport parameters\n" - "Configure prefered address family for TCP transport connection with neighbor\n" + "Configure preferred address family for TCP transport connection with neighbor\n" "IPv4\n") { return (ldp_vty_trans_pref_ipv4(vty, no)); diff --git a/ldpd/util.c b/ldpd/util.c index 12f9cb0ccf..b4d74f1950 100644 --- a/ldpd/util.c +++ b/ldpd/util.c @@ -259,7 +259,7 @@ embedscope(struct sockaddr_in6 *sin6) if (IN6_IS_SCOPE_EMBED(&sin6->sin6_addr)) { memcpy(&tmp16, &sin6->sin6_addr.s6_addr[2], sizeof(tmp16)); if (tmp16 != 0) { - log_warnx("%s: address %s already has embeded scope %u", + log_warnx("%s: address %s already has embedded scope %u", __func__, log_sockaddr(sin6), ntohs(tmp16)); } tmp16 = htons(sin6->sin6_scope_id); diff --git a/lib/bfd.c b/lib/bfd.c index 1dfe583caf..178c203f5e 100644 --- a/lib/bfd.c +++ b/lib/bfd.c @@ -134,7 +134,7 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, int ret; int len; - /* Individual reg/dereg messages are supressed during shutdown. */ + /* Individual reg/dereg messages are suppressed during shutdown. */ if (CHECK_FLAG(bfd_gbl.flags, BFD_GBL_FLAG_IN_SHUTDOWN)) { if (bfd_debug) zlog_debug( diff --git a/lib/command.c b/lib/command.c index 60c5f4e75b..127e1a0a0a 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,18 @@ 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 && + ret != CMD_SUCCESS_DAEMON) { + 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 +1348,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..de65c8bd98 100644 --- a/lib/command.h +++ b/lib/command.h @@ -355,7 +355,7 @@ struct cmd_node { #define IN_STR "Filter incoming routing updates\n" #define V4NOTATION_STR "specify by IPv4 address notation(e.g. 0.0.0.0)\n" #define OSPF6_NUMBER_STR "Specify by number\n" -#define INTERFACE_STR "Interface infomation\n" +#define INTERFACE_STR "Interface information\n" #define IFNAME_STR "Interface name(e.g. ep0)\n" #define IP6_STR "IPv6 Information\n" #define OSPF6_STR "Open Shortest Path First (OSPF) for IPv6\n" @@ -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/command_lex.l b/lib/command_lex.l index 3b18b58a2e..f361db78e9 100644 --- a/lib/command_lex.l +++ b/lib/command_lex.l @@ -48,8 +48,8 @@ IPV4 A\.B\.C\.D IPV4_PREFIX A\.B\.C\.D\/M IPV6 X:X::X:X IPV6_PREFIX X:X::X:X\/M -MAC M:A:C -MAC_PREFIX M:A:C\/M +MAC X:X:X:X:X:X +MAC_PREFIX X:X:X:X:X:X\/M VARIABLE [A-Z][-_A-Z:0-9]+ WORD (\-|\+)?[a-zA-Z0-9\*][-+_a-zA-Z0-9\*]* NUMBER (\-|\+)?[0-9]{1,20} 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/filter.c b/lib/filter.c index 0528b0f2ad..1aae58b61c 100644 --- a/lib/filter.c +++ b/lib/filter.c @@ -1302,7 +1302,7 @@ static int filter_set_zebra(struct vty *vty, const char *name_str, DEFUN (mac_access_list, mac_access_list_cmd, - "mac access-list WORD MAC", + "mac access-list WORD X:X:X:X:X:X", "Add a mac access-list\n" "Add an access list entry\n" "MAC zebra access-list name\n" @@ -1316,7 +1316,7 @@ DEFUN (mac_access_list, DEFUN (no_mac_access_list, no_mac_access_list_cmd, - "no mac access-list WORD MAC", + "no mac access-list WORD X:X:X:X:X:X", NO_STR "Remove a mac access-list\n" "Remove an access list entry\n" 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; diff --git a/lib/lib_errors.c b/lib/lib_errors.c index 03ad974da6..ad83ef1e51 100644 --- a/lib/lib_errors.c +++ b/lib/lib_errors.c @@ -89,8 +89,8 @@ static struct log_ref ferr_lib_err[] = { { .code = EC_LIB_SOCKET, .title = "Socket Error", - .description = "When attempting to access a socket a system error has occured and we were unable to properly complete the request", - .suggestion = "Ensure that there are sufficient system resources available and ensure that the frr user has sufficient permisions to work. If necessary open an Issue", + .description = "When attempting to access a socket a system error has occurred and we were unable to properly complete the request", + .suggestion = "Ensure that there are sufficient system resources available and ensure that the frr user has sufficient permissions to work. If necessary open an Issue", }, { .code = EC_LIB_ZAPI_MISSMATCH, diff --git a/lib/log.c b/lib/log.c index 2d800baae1..5cc303daf0 100644 --- a/lib/log.c +++ b/lib/log.c @@ -38,6 +38,12 @@ #include #endif +#ifdef HAVE_LIBUNWIND +#define UNW_LOCAL_ONLY +#include +#include +#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, ...) @@ -980,6 +1049,7 @@ static const struct zebra_desc_table command_types[] = { DESC_ENTRY(ZEBRA_IPSET_DESTROY), DESC_ENTRY(ZEBRA_IPSET_ENTRY_ADD), DESC_ENTRY(ZEBRA_IPSET_ENTRY_DELETE), + DESC_ENTRY(ZEBRA_VXLAN_FLOOD_CONTROL), }; #undef DESC_ENTRY diff --git a/lib/mpls.h b/lib/mpls.h index c9dd60dce0..6146985610 100644 --- a/lib/mpls.h +++ b/lib/mpls.h @@ -171,7 +171,7 @@ static inline char *label2str(mpls_label_t label, char *buf, size_t len) strlcpy(buf, "Router Alert", len); return (buf); case MPLS_LABEL_IPV6_EXPLICIT_NULL: - strlcpy(buf, "IPv6 Explict Null", len); + strlcpy(buf, "IPv6 Explicit Null", len); return (buf); case MPLS_LABEL_IMPLICIT_NULL: strlcpy(buf, "implicit-null", len); 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 bc45cd51d0..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 *); @@ -811,6 +810,18 @@ struct route_map *route_map_lookup_by_name(const char *name) return map; } +/* Simple helper to warn if route-map does not exist. */ +struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *name) +{ + struct route_map *route_map = route_map_lookup_by_name(name); + + if (!route_map) + if (vty_shell_serv(vty)) + vty_out(vty, "The route-map '%s' does not exist.\n", name); + + return route_map; +} + int route_map_mark_updated(const char *name) { struct route_map *map; @@ -1612,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, @@ -2239,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/routemap.h b/lib/routemap.h index 481b8c4a9a..463aa91725 100644 --- a/lib/routemap.h +++ b/lib/routemap.h @@ -220,6 +220,9 @@ extern void route_map_install_set(struct route_map_rule_cmd *cmd); /* Lookup route map by name. */ extern struct route_map *route_map_lookup_by_name(const char *name); +/* Simple helper to warn if route-map does not exist. */ +struct route_map *route_map_lookup_warn_noexist(struct vty *vty, const char *name); + /* Apply route map to the object. */ extern route_map_result_t route_map_apply(struct route_map *map, const struct prefix *prefix, diff --git a/lib/sockunion.c b/lib/sockunion.c index bee82a067e..af4f41f37c 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -356,7 +356,7 @@ int sockopt_ttl(int family, int sock, int ttl) * Which on linux is a no-op since it is enabled by * default and on BSD it uses TCP_NOPUSH to do * the same thing( which it was not configured to - * use). This cleanup of the api occured on 8/1/17 + * use). This cleanup of the api occurred on 8/1/17 * I imagine if after more than 1 year of no-one * complaining, and a major upgrade release we * can deprecate and remove this function call diff --git a/lib/subdir.am b/lib/subdir.am index dd2731f74c..e2571f0c67 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 \ @@ -336,6 +336,7 @@ lib/lib_clippy-command_parse.$(OBJEXT): lib/command_lex.h lib/route_types.h: $(top_srcdir)/lib/route_types.txt $(top_srcdir)/lib/route_types.pl @PERL@ $(top_srcdir)/lib/route_types.pl < $(top_srcdir)/lib/route_types.txt > $@ +DISTCLEANFILES += lib/route_types.h if GIT_VERSION # bit of a trick here to always have up-to-date git stamps without triggering 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"); diff --git a/lib/vrf.c b/lib/vrf.c index eca9913e1f..498aef4580 100644 --- a/lib/vrf.c +++ b/lib/vrf.c @@ -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; diff --git a/lib/vty.c b/lib/vty.c index f812dd4279..a73cc23b97 100644 --- a/lib/vty.c +++ b/lib/vty.c @@ -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); diff --git a/lib/vty.h b/lib/vty.h index b55abf2204..efe91a568b 100644 --- a/lib/vty.h +++ b/lib/vty.h @@ -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/lib/vxlan.h b/lib/vxlan.h index ba3dbb05c8..bcf8354539 100644 --- a/lib/vxlan.h +++ b/lib/vxlan.h @@ -26,4 +26,13 @@ typedef uint32_t vni_t; #define VNI_MAX 16777215 /* (2^24 - 1) */ +/* Flooding mechanisms for BUM packets. */ +/* Currently supported mechanisms are head-end (ingress) replication + * (which is the default) and no flooding. Future options could be + * using PIM-SM, PIM-Bidir etc. + */ +enum vxlan_flood_control { + VXLAN_FLOOD_HEAD_END_REPL = 0, + VXLAN_FLOOD_DISABLED, +}; #endif /* __VXLAN_H__ */ diff --git a/lib/zclient.h b/lib/zclient.h index 54f3635901..97ebb0811c 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -155,6 +155,7 @@ typedef enum { ZEBRA_IPTABLE_ADD, ZEBRA_IPTABLE_DELETE, ZEBRA_IPTABLE_NOTIFY_OWNER, + ZEBRA_VXLAN_FLOOD_CONTROL, } zebra_message_types_t; struct redist_proto { diff --git a/m4/ax_sys_weak_alias.m4 b/m4/ax_sys_weak_alias.m4 index 27b0f0c4f0..37cbe9187c 100644 --- a/m4/ax_sys_weak_alias.m4 +++ b/m4/ax_sys_weak_alias.m4 @@ -22,7 +22,7 @@ # another object file. # # There are four known schemes of declaring weak symbols; each scheme is -# checked in turn, and the first one found is prefered. Note that only one +# checked in turn, and the first one found is preferred. Note that only one # of the mentioned preprocessor macros will be defined! # # 1. Function attributes 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_abr.c b/ospf6d/ospf6_abr.c index 1890e9bdc3..53d545a24b 100644 --- a/ospf6d/ospf6_abr.c +++ b/ospf6d/ospf6_abr.c @@ -321,7 +321,7 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route, /* if this is a route to ASBR */ if (route->type == OSPF6_DEST_TYPE_ROUTER) { - /* Only the prefered best path is considered */ + /* Only the preferred best path is considered */ if (!CHECK_FLAG(route->flag, OSPF6_ROUTE_BEST)) { if (is_debug) zlog_debug( diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c index c848a16aa9..bc52864313 100644 --- a/ospf6d/ospf6_area.c +++ b/ospf6d/ospf6_area.c @@ -772,7 +772,7 @@ DEFUN (show_ipv6_ospf6_spf_tree, SHOW_STR IP6_STR OSPF6_STR - "Shortest Path First caculation\n" + "Shortest Path First calculation\n" "Show SPF tree\n") { struct listnode *node; @@ -807,7 +807,7 @@ DEFUN (show_ipv6_ospf6_area_spf_tree, OSPF6_STR OSPF6_AREA_STR OSPF6_AREA_ID_STR - "Shortest Path First caculation\n" + "Shortest Path First calculation\n" "Show SPF tree\n") { int idx_ipv4 = 4; 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 [] []", + "show ipv6 ospf6 interface IFNAME prefix\ + [<\ + 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 [] []", + "show ipv6 ospf6 interface prefix\ + [<\ + 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_intra.c b/ospf6d/ospf6_intra.c index 0ce08a61e2..7ae7d682bd 100644 --- a/ospf6d/ospf6_intra.c +++ b/ospf6d/ospf6_intra.c @@ -1729,7 +1729,7 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa) listnode_add_sort(route->paths, path); old = ospf6_route_lookup(&route->prefix, oa->route_table); - if (old && (ospf6_route_cmp(route, old) == 0)) { + if (old) { if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX)) { prefix2str(&route->prefix, buf, sizeof(buf)); zlog_debug("%s Update route: %s old cost %u new cost %u paths %u nh %u", 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/ospfclient/subdir.am b/ospfclient/subdir.am index d42c5b450e..c05d920d5f 100644 --- a/ospfclient/subdir.am +++ b/ospfclient/subdir.am @@ -4,7 +4,7 @@ if OSPFCLIENT lib_LTLIBRARIES += ospfclient/libfrrospfapiclient.la -sbin_PROGRAMS += ospfclient/ospfclient +noinst_PROGRAMS += ospfclient/ospfclient man8 += $(MANBUILD)/ospfclient.8 endif diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c index 8078455930..714c47b4e6 100644 --- a/ospfd/ospf_flood.c +++ b/ospfd/ospf_flood.c @@ -91,7 +91,7 @@ struct external_info *ospf_external_info_check(struct ospf *ospf, p.prefix = lsa->data->id; p.prefixlen = ip_masklen(al->mask); - for (type = 0; type < ZEBRA_ROUTE_MAX; type++) { + for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) { int redist_on = 0; redist_on = diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c index ad9b3efe6e..9fd9a70c78 100644 --- a/ospfd/ospf_ism.c +++ b/ospfd/ospf_ism.c @@ -277,7 +277,7 @@ static int ospf_wait_timer(struct thread *thread) return 0; } -/* Hook function called after ospf ISM event is occured. And vty's +/* Hook function called after ospf ISM event is occurred. And vty's network command invoke this function after making interface structure. */ static void ism_timer_set(struct ospf_interface *oi) diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c index 91d187f412..f7c73fee33 100644 --- a/ospfd/ospf_nsm.c +++ b/ospfd/ospf_nsm.c @@ -94,7 +94,7 @@ static int ospf_db_desc_timer(struct thread *thread) return 0; } -/* Hook function called after ospf NSM event is occured. +/* Hook function called after ospf NSM event is occurred. * * Set/clear any timers whose condition is implicit to the neighbour * state. There may be other timers which are set/unset according to other diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c index 7f96299768..147773ce23 100644 --- a/ospfd/ospf_opaque.c +++ b/ospfd/ospf_opaque.c @@ -500,7 +500,7 @@ struct opaque_info_per_type { /* Collection of callback functions for this opaque-type. */ struct ospf_opaque_functab *functab; - /* List of Opaque-LSA control informations per opaque-id. */ + /* List of Opaque-LSA control information per opaque-id. */ struct list *id_list; }; diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c index 359d59cb58..3bb3b79a6a 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; } @@ -3370,7 +3368,7 @@ static int ospf_make_db_desc(struct ospf_interface *oi, if (IS_OPAQUE_LSA(lsa->data->type) && (!CHECK_FLAG(options, OSPF_OPTION_O))) { /* Suppress advertising - * opaque-informations. */ + * opaque-information. */ /* Remove LSA from DB summary list. */ ospf_lsdb_delete(lsdb, lsa); continue; diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c index 3b0319b591..bef16761f2 100644 --- a/ospfd/ospf_ri.c +++ b/ospfd/ospf_ri.c @@ -591,7 +591,7 @@ static int is_mandated_params_set(struct ospf_router_info ori) * @param enable To activate or not Segment Routing router Information flooding * @param size Size of Label Range i.e. SRGB size * @param lower Lower bound of the Label Range i.e. SRGB first label - * @param msd Maximum label Stack Depth suported by the router + * @param msd Maximum label Stack Depth supported by the router * * @return none */ 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/ospfd/ospf_te.c b/ospfd/ospf_te.c index f43038ab8d..02698d770a 100644 --- a/ospfd/ospf_te.c +++ b/ospfd/ospf_te.c @@ -2406,7 +2406,7 @@ DEFUN (no_ospf_mpls_te_inter_as, ospf_mpls_te_lsa_schedule(lp, FLUSH_THIS_LSA); } - /* Deregister the Callbacks for Inter-AS suport */ + /* Deregister the Callbacks for Inter-AS support */ ospf_mpls_te_unregister(); return CMD_SUCCESS; diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c index 25d54a8553..652c47387a 100644 --- a/ospfd/ospf_vty.c +++ b/ospfd/ospf_vty.c @@ -8387,6 +8387,9 @@ DEFUN (ospf_default_information_originate, int metric = -1; struct ospf_redist *red; int idx = 0; + int cur_originate = ospf->default_originate; + int sameRtmap = 0; + char *rtmap = NULL; red = ospf_redist_add(ospf, DEFAULT_ROUTE, 0); @@ -8408,7 +8411,28 @@ DEFUN (ospf_default_information_originate, idx = 1; /* Get route-map */ if (argv_find(argv, argc, "WORD", &idx)) - ospf_routemap_set(red, argv[idx]->arg); + rtmap = argv[idx]->arg; + + /* To check ,if user is providing same route map */ + if ((rtmap == ROUTEMAP_NAME(red)) || + (rtmap && ROUTEMAP_NAME(red) + && (strcmp(rtmap, ROUTEMAP_NAME(red)) == 0))) + sameRtmap = 1; + + /* Don't allow if the same lsa is aleardy originated. */ + if ((sameRtmap) + && (red->dmetric.type == type) + && (red->dmetric.value == metric) + && (cur_originate == default_originate)) + return CMD_SUCCESS; + + /* Updating Metric details */ + red->dmetric.type = type; + red->dmetric.value = metric; + + /* updating route map details */ + if (rtmap) + ospf_routemap_set(red, rtmap); else ospf_routemap_unset(red); diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c index fdb87bd1ff..ed19ae4f31 100644 --- a/ospfd/ospf_zebra.c +++ b/ospfd/ospf_zebra.c @@ -626,6 +626,8 @@ struct ospf_redist *ospf_redist_add(struct ospf *ospf, uint8_t type, red->instance = instance; red->dmetric.type = -1; red->dmetric.value = -1; + ROUTEMAP_NAME(red) = NULL; + ROUTEMAP(red) = NULL; listnode_add(red_list, red); @@ -753,11 +755,54 @@ int ospf_redistribute_unset(struct ospf *ospf, int type, int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, int mvalue) { + struct ospf_external *ext; + struct prefix_ipv4 p; + struct in_addr nexthop; + int cur_originate = ospf->default_originate; + + nexthop.s_addr = 0; + p.family = AF_INET; + p.prefix.s_addr = 0; + p.prefixlen = 0; + ospf->default_originate = originate; ospf_external_add(ospf, DEFAULT_ROUTE, 0); - if (ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) + if (cur_originate == DEFAULT_ORIGINATE_NONE) { + /* First time configuration */ + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) + zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", + metric_type(ospf, DEFAULT_ROUTE, 0), + metric_value(ospf, DEFAULT_ROUTE, 0)); + + if (ospf->router_id.s_addr == 0) + ospf->external_origin |= (1 << DEFAULT_ROUTE); + if ((originate == DEFAULT_ORIGINATE_ALWAYS) + && (ospf->router_id.s_addr)) { + + /* always , so originate lsa even it doesn't + * exist in RIB. + */ + ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, + p, 0, nexthop, 0); + ospf_external_lsa_refresh_default(ospf); + + } else if (originate == DEFAULT_ORIGINATE_ZEBRA) { + /* Send msg to Zebra to validate default route + * existance. + */ + zclient_redistribute_default( + ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + zclient, ospf->vrf_id); + } + + ospf_asbr_status_update(ospf, ++ospf->redistribute); + return CMD_SUCCESS; + + + } else if (originate == cur_originate) { + /* Refresh the lsa since metric might different */ if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug( "Redistribute[%s]: Refresh Type[%d], Metric[%d]", @@ -765,37 +810,58 @@ int ospf_redistribute_default_set(struct ospf *ospf, int originate, int mtype, metric_type(ospf, DEFAULT_ROUTE, 0), metric_value(ospf, DEFAULT_ROUTE, 0)); - zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD, zclient, - ospf->vrf_id); + ospf_external_lsa_refresh_default(ospf); - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) - zlog_debug("Redistribute[DEFAULT]: Start Type[%d], Metric[%d]", - metric_type(ospf, DEFAULT_ROUTE, 0), - metric_value(ospf, DEFAULT_ROUTE, 0)); + } else { + /* "default-info originate always" configured now, + * where "default-info originate" configured previoulsly. + */ + if (originate == DEFAULT_ORIGINATE_ALWAYS) { - ospf_external_lsa_refresh_default(ospf); + zclient_redistribute_default( + ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + zclient, ospf->vrf_id); + /* here , ex-info should be added since ex-info might + * have not updated earlier if def route is not exist. + * If ex-iinfo ex-info already exist , it will return + * smoothly. + */ + ospf_external_info_add(ospf, DEFAULT_ROUTE, 0, + p, 0, nexthop, 0); + ospf_external_lsa_refresh_default(ospf); - if (ospf->router_id.s_addr == 0) - ospf->external_origin |= (1 << DEFAULT_ROUTE); - else - thread_add_timer(master, ospf_default_originate_timer, ospf, 1, - NULL); + } else { + /* "default-info originate" configured now,where + * "default-info originate always" configured + * previoulsy. + */ - ospf_asbr_status_update(ospf, ++ospf->redistribute); + ospf_external_lsa_flush(ospf, DEFAULT_ROUTE, &p, 0); + + ext = ospf_external_lookup(ospf, DEFAULT_ROUTE, 0); + if (ext && EXTERNAL_INFO(ext)) + ospf_external_info_delete(ospf, + DEFAULT_ROUTE, 0, p); + + zclient_redistribute_default( + ZEBRA_REDISTRIBUTE_DEFAULT_ADD, + zclient, ospf->vrf_id); + } + } return CMD_SUCCESS; } - int ospf_redistribute_default_unset(struct ospf *ospf) { - if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) - return CMD_SUCCESS; + if (ospf->default_originate == DEFAULT_ORIGINATE_ZEBRA) { + if (!ospf_is_type_redistributed(ospf, DEFAULT_ROUTE, 0)) + return CMD_SUCCESS; + zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, + zclient, ospf->vrf_id); + } ospf->default_originate = DEFAULT_ORIGINATE_NONE; - zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_DELETE, zclient, - ospf->vrf_id); - if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) zlog_debug("Redistribute[DEFAULT]: Stop"); @@ -941,6 +1007,7 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, struct external_info *ei; struct ospf *ospf; int i; + uint8_t rt_type; ospf = ospf_lookup_by_vrf_id(vrf_id); if (ospf == NULL) @@ -951,11 +1018,21 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, ifindex = api.nexthops[0].ifindex; nexthop = api.nexthops[0].gate.ipv4; + rt_type = api.type; memcpy(&p, &api.prefix, sizeof(p)); if (IPV4_NET127(ntohl(p.prefix.s_addr))) return 0; + /* Re-destributed route is default route. + * Here, route type is used as 'ZEBRA_ROUTE_KERNEL' for + * updating ex-info. But in resetting (no default-info + * originate)ZEBRA_ROUTE_MAX is used to delete the ex-info. + * Resolved this inconsistency by maintaining same route type. + */ + if (is_prefix_default(&p)) + rt_type = DEFAULT_ROUTE; + if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE)) { char buf_prefix[PREFIX_STRLEN]; prefix2str(&api.prefix, buf_prefix, sizeof(buf_prefix)); @@ -973,8 +1050,8 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, */ /* Protocol tag overwrites all other tag value sent by zebra */ - if (ospf->dtag[api.type] > 0) - api.tag = ospf->dtag[api.type]; + if (ospf->dtag[rt_type] > 0) + api.tag = ospf->dtag[rt_type]; /* * Given zebra sends update for a prefix via ADD message, it @@ -983,12 +1060,12 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, * source * types. */ - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) - if (i != api.type) + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) + if (i != rt_type) ospf_external_info_delete(ospf, i, api.instance, p); - ei = ospf_external_info_add(ospf, api.type, api.instance, p, + ei = ospf_external_info_add(ospf, rt_type, api.instance, p, ifindex, nexthop, api.tag); if (ei == NULL) { /* Nothing has changed, so nothing to do; return */ @@ -997,7 +1074,7 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, if (ospf->router_id.s_addr == 0) /* Set flags to generate AS-external-LSA originate event for each redistributed protocols later. */ - ospf->external_origin |= (1 << api.type); + ospf->external_origin |= (1 << rt_type); else { if (ei) { if (is_prefix_default(&p)) @@ -1027,11 +1104,11 @@ static int ospf_zebra_read_route(int command, struct zclient *zclient, } } else /* if (command == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */ { - ospf_external_info_delete(ospf, api.type, api.instance, p); + ospf_external_info_delete(ospf, rt_type, api.instance, p); if (is_prefix_default(&p)) ospf_external_lsa_refresh_default(ospf); else - ospf_external_lsa_flush(ospf, api.type, &p, + ospf_external_lsa_flush(ospf, rt_type, &p, ifindex /*, nexthop */); } diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c index dc54f04c07..aa40dd0ebc 100644 --- a/ospfd/ospfd.c +++ b/ospfd/ospfd.c @@ -171,7 +171,7 @@ void ospf_router_id_update(struct ospf *ospf) /* Flush (inline) all external LSAs which now match the new router-id, - need to adjust the OSPF_LSA_SELF flag, so the flush doesnt + need to adjust the OSPF_LSA_SELF flag, so the flush doesn't hit asserts in ospf_refresher_unregister_lsa(). This step is needed 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/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index 25d64238bf..b7391a171a 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -207,13 +207,13 @@ static int rule_notify_owner(int command, struct zclient *zclient, switch (note) { case ZAPI_RULE_FAIL_INSTALL: - DEBUGD(&pbr_dbg_zebra, "%s: Recieved RULE_FAIL_INSTALL", + DEBUGD(&pbr_dbg_zebra, "%s: Received RULE_FAIL_INSTALL", __PRETTY_FUNCTION__); pbrms->installed &= ~installed; break; case ZAPI_RULE_INSTALLED: pbrms->installed |= installed; - DEBUGD(&pbr_dbg_zebra, "%s: Recived RULE_INSTALLED", + DEBUGD(&pbr_dbg_zebra, "%s: Received RULE_INSTALLED", __PRETTY_FUNCTION__); break; case ZAPI_RULE_FAIL_REMOVE: 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_instance.c b/pimd/pim_instance.c index 2550651464..b0d7a7b2db 100644 --- a/pimd/pim_instance.c +++ b/pimd/pim_instance.c @@ -188,7 +188,7 @@ static int pim_vrf_config_write(struct vty *vty) pim_global_config_write_worker(pim, vty); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, "!\n"); + vty_endframe(vty, " exit-vrf\n!\n"); } return 0; diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c index 436e0508f3..dc4c4402a1 100644 --- a/pimd/pim_mroute.c +++ b/pimd/pim_mroute.c @@ -48,8 +48,8 @@ static void mroute_read_on(struct pim_instance *pim); static int pim_mroute_set(struct pim_instance *pim, int enable) { int err; - int opt; - socklen_t opt_len = sizeof(opt); + int opt, data; + socklen_t data_len = sizeof(data); long flags; /* @@ -58,15 +58,15 @@ static int pim_mroute_set(struct pim_instance *pim, int enable) if (pim->vrf_id != VRF_DEFAULT) { frr_elevate_privs(&pimd_privs) { - opt = pim->vrf->data.l.table_id; + data = pim->vrf->data.l.table_id; err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_TABLE, - &opt, opt_len); + &data, data_len); if (err) { zlog_warn( "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s", __FILE__, __PRETTY_FUNCTION__, - pim->mroute_socket, opt, errno, + pim->mroute_socket, data, errno, safe_strerror(errno)); return -1; } @@ -74,23 +74,32 @@ static int pim_mroute_set(struct pim_instance *pim, int enable) } } - opt = enable ? MRT_INIT : MRT_DONE; - err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &opt, opt_len); - if (err) { - zlog_warn( - "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", - __FILE__, __PRETTY_FUNCTION__, pim->mroute_socket, - enable ? "MRT_INIT" : "MRT_DONE", opt, errno, - safe_strerror(errno)); - return -1; + frr_elevate_privs(&pimd_privs) { + opt = enable ? MRT_INIT : MRT_DONE; + /* + * *BSD *cares* about what value we pass down + * here + */ + data = 1; + err = setsockopt(pim->mroute_socket, IPPROTO_IP, + opt, &data, data_len); + if (err) { + zlog_warn( + "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s", + __FILE__, __PRETTY_FUNCTION__, + pim->mroute_socket, + enable ? "MRT_INIT" : "MRT_DONE", data, errno, + safe_strerror(errno)); + return -1; + } } #if defined(HAVE_IP_PKTINFO) if (enable) { /* Linux and Solaris IP_PKTINFO */ - opt = 1; - if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO, &opt, - sizeof(opt))) { + data = 1; + if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO, + &data, data_len)) { zlog_warn( "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s", pim->mroute_socket, errno, diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 9ef343a0c5..7e072e6ade 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -74,7 +74,7 @@ static int pim_msdp_sa_adv_timer_cb(struct thread *t) struct pim_instance *pim = THREAD_ARG(t); if (PIM_DEBUG_MSDP_EVENTS) { - zlog_debug("MSDP SA advertisment timer expired"); + zlog_debug("MSDP SA advertisement timer expired"); } pim_msdp_sa_adv_timer_setup(pim, true /* start */); @@ -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..cd5b632ded 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -462,7 +462,7 @@ static int pim_upstream_could_register(struct pim_upstream *up) return 0; } -/* Source registration is supressed for SSM groups. When the SSM range changes +/* Source registration is suppressed for SSM groups. When the SSM range changes * we re-revaluate register setup for existing upstream entries */ void pim_upstream_register_reevaluate(struct pim_instance *pim) { @@ -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/redhat/frr.spec.in b/redhat/frr.spec.in index 1395af5dfb..8e6ddfbdb2 100644 --- a/redhat/frr.spec.in +++ b/redhat/frr.spec.in @@ -144,7 +144,7 @@ Summary: Routing daemon Name: frr Version: %{rpmversion} -Release: @CONFDATE@%{release_rev}%{?dist} +Release: %{release_rev}%{?dist} License: GPLv2+ Group: System Environment/Daemons Source0: https://github.com/FRRouting/frr/archive/%{name}-%{frrversion}.tar.gz @@ -647,9 +647,6 @@ fi %files devel %{_libdir}/lib*.so -%if %{with_ospfclient} - %{_sbindir}/ospfclient -%endif %dir %{_includedir}/%{name} %{_includedir}/%{name}/*.h %dir %{_includedir}/%{name}/ospfd 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/ripd/ripd.c b/ripd/ripd.c index 444a09914c..dd0d17ee47 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1238,7 +1238,7 @@ static void rip_response_process(struct rip_packet *packet, int size, Ciscos before the 'ip subnet zero' option, it would be almost right too :-) - Cisco summarize ripv1 advertisments to the classful boundary + Cisco summarize ripv1 advertisements to the classful boundary (/16 for class B's) except when the RIP packet does to inside the classful network in question. */ @@ -2513,7 +2513,7 @@ static void rip_update_process(int route_type) VRF_DEFAULT); if (!connected) { zlog_warn( - "Neighbor %s doesnt have connected interface!", + "Neighbor %s doesn't have connected interface!", inet_ntoa(p->u.prefix4)); continue; } 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/ripngd/ripngd.c b/ripngd/ripngd.c index 08dc3d8b4d..2cbbbae7f5 100644 --- a/ripngd/ripngd.c +++ b/ripngd/ripngd.c @@ -1560,7 +1560,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, && rinfo->suppress == 0) { /* If no route-map are applied, the RTE will be these * following - * informations. + * information. */ p = (struct prefix_ipv6 *)&rp->p; rinfo->metric_out = rinfo->metric; @@ -1701,7 +1701,7 @@ void ripng_output_process(struct interface *ifp, struct sockaddr_in6 *to, && aggregate->suppress == 0) { /* If no route-map are applied, the RTE will be these * following - * informations. + * information. */ p = (struct prefix_ipv6 *)&rp->p; aggregate->metric_set = 0; 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_vrf.c b/staticd/static_vrf.c index ad143209ee..9dd25fbdd1 100644 --- a/staticd/static_vrf.c +++ b/staticd/static_vrf.c @@ -164,7 +164,7 @@ static int static_vrf_config_write(struct vty *vty) SAFI_UNICAST, "ipv6 route"); if (vrf->vrf_id != VRF_DEFAULT) - vty_endframe(vty, "!\n"); + vty_endframe(vty, " exit-vrf\n!\n"); } return 0; diff --git a/staticd/static_vty.c b/staticd/static_vty.c index f697969a72..bc8a429d56 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; @@ -198,7 +199,7 @@ static int zebra_static_route_holdem( 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 *table_str, bool onlink) { struct static_hold_route *shr, *lookup; struct listnode *node; @@ -211,6 +212,7 @@ static int zebra_static_route_holdem( shr->nhvrf_name = XSTRDUP(MTYPE_STATIC_ROUTE, nh_svrf->vrf->name); shr->afi = afi; shr->safi = safi; + shr->onlink = onlink; if (dest) prefix_copy(&shr->dest, dest); if (dest_str) @@ -273,7 +275,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; @@ -345,7 +348,7 @@ static int static_route_leak( return zebra_static_route_holdem( svrf, nh_svrf, afi, safi, negate, &p, dest_str, mask_str, src_str, gate_str, ifname, flag_str, tag_str, - distance_str, label_str, table_str); + distance_str, label_str, table_str, onlink); } if (table_str) { @@ -509,7 +512,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 +553,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 +581,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( @@ -643,7 +647,9 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, if (shr->table_str) vty_out(vty, "table %s", shr->table_str); if (strcmp(shr->vrf_name, shr->nhvrf_name) != 0) - vty_out(vty, "nexthop-vrf %s", shr->nhvrf_name); + vty_out(vty, "nexthop-vrf %s ", shr->nhvrf_name); + if (shr->onlink) + vty_out(vty, "onlink"); vty_out(vty, "\n"); } @@ -714,6 +720,9 @@ int static_config(struct vty *vty, struct static_vrf *svrf, afi_t afi, svrf->vrf->data.l.table_id == RT_TABLE_MAIN) vty_out(vty, " table %u", si->table_id); + if (si->onlink) + vty_out(vty, " onlink"); + vty_out(vty, "\n"); write = 1; @@ -817,9 +826,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 +845,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 +862,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 +896,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 +914,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 +930,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 +959,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 +1028,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 +1087,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 +1173,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 +1188,7 @@ DEFPY(ipv6_route_address_interface, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IPV6_STR @@ -1190,7 +1205,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 +1236,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 +1250,7 @@ DEFPY(ipv6_route_address_interface_vrf, |label WORD \ |table (1-4294967295) \ |nexthop-vrf NAME \ + |onlink$onlink \ }]", NO_STR IPV6_STR @@ -1249,7 +1266,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 +1292,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 +1352,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 +1405,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/bgpd/test_mpath.c b/tests/bgpd/test_mpath.c index 42f7d76759..f0797827ce 100644 --- a/tests/bgpd/test_mpath.c +++ b/tests/bgpd/test_mpath.c @@ -207,7 +207,7 @@ struct peer test_mp_list_peer[] = { }; int test_mp_list_peer_count = sizeof(test_mp_list_peer) / sizeof(struct peer); struct attr test_mp_list_attr[4]; -struct bgp_info test_mp_list_info[] = { +struct bgp_path_info test_mp_list_info[] = { {.peer = &test_mp_list_peer[0], .attr = &test_mp_list_attr[0]}, {.peer = &test_mp_list_peer[1], .attr = &test_mp_list_attr[1]}, {.peer = &test_mp_list_peer[2], .attr = &test_mp_list_attr[1]}, @@ -215,7 +215,7 @@ struct bgp_info test_mp_list_info[] = { {.peer = &test_mp_list_peer[4], .attr = &test_mp_list_attr[3]}, }; int test_mp_list_info_count = - sizeof(test_mp_list_info) / sizeof(struct bgp_info); + sizeof(test_mp_list_info) / sizeof(struct bgp_path_info); static int setup_bgp_mp_list(testcase_t *t) { @@ -247,7 +247,7 @@ static int run_bgp_mp_list(testcase_t *t) { struct list mp_list; struct listnode *mp_node; - struct bgp_info *info; + struct bgp_path_info *info; int i; int test_result = TEST_PASSED; bgp_mp_list_init(&mp_list); @@ -289,24 +289,24 @@ testcase_t test_bgp_mp_list = { }; /*========================================================= - * Testcase for bgp_info_mpath_update + * Testcase for bgp_path_info_mpath_update */ struct bgp_node test_rn; -static int setup_bgp_info_mpath_update(testcase_t *t) +static int setup_bgp_path_info_mpath_update(testcase_t *t) { int i; str2prefix("42.1.1.0/24", &test_rn.p); setup_bgp_mp_list(t); for (i = 0; i < test_mp_list_info_count; i++) - bgp_info_add(&test_rn, &test_mp_list_info[i]); + bgp_path_info_add(&test_rn, &test_mp_list_info[i]); return 0; } -static int run_bgp_info_mpath_update(testcase_t *t) +static int run_bgp_path_info_mpath_update(testcase_t *t) { - struct bgp_info *new_best, *old_best, *mpath; + struct bgp_path_info *new_best, *old_best, *mpath; struct list mp_list; struct bgp_maxpaths_cfg mp_cfg = {3, 3}; int test_result = TEST_PASSED; @@ -317,33 +317,35 @@ static int run_bgp_info_mpath_update(testcase_t *t) bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); new_best = &test_mp_list_info[3]; old_best = NULL; - bgp_info_mpath_update(&test_rn, new_best, old_best, &mp_list, &mp_cfg); + bgp_path_info_mpath_update(&test_rn, new_best, old_best, &mp_list, + &mp_cfg); bgp_mp_list_clear(&mp_list); - EXPECT_TRUE(bgp_info_mpath_count(new_best) == 2, test_result); - mpath = bgp_info_mpath_first(new_best); + EXPECT_TRUE(bgp_path_info_mpath_count(new_best) == 2, test_result); + mpath = bgp_path_info_mpath_first(new_best); EXPECT_TRUE(mpath == &test_mp_list_info[0], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); - mpath = bgp_info_mpath_next(mpath); + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); + mpath = bgp_path_info_mpath_next(mpath); EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); bgp_mp_list_add(&mp_list, &test_mp_list_info[0]); bgp_mp_list_add(&mp_list, &test_mp_list_info[1]); new_best = &test_mp_list_info[0]; old_best = &test_mp_list_info[3]; - bgp_info_mpath_update(&test_rn, new_best, old_best, &mp_list, &mp_cfg); + bgp_path_info_mpath_update(&test_rn, new_best, old_best, &mp_list, + &mp_cfg); bgp_mp_list_clear(&mp_list); - EXPECT_TRUE(bgp_info_mpath_count(new_best) == 1, test_result); - mpath = bgp_info_mpath_first(new_best); + EXPECT_TRUE(bgp_path_info_mpath_count(new_best) == 1, test_result); + mpath = bgp_path_info_mpath_first(new_best); EXPECT_TRUE(mpath == &test_mp_list_info[1], test_result); - EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_INFO_MULTIPATH), test_result); - EXPECT_TRUE(!CHECK_FLAG(test_mp_list_info[0].flags, BGP_INFO_MULTIPATH), + EXPECT_TRUE(CHECK_FLAG(mpath->flags, BGP_PATH_MULTIPATH), test_result); + EXPECT_TRUE(!CHECK_FLAG(test_mp_list_info[0].flags, BGP_PATH_MULTIPATH), test_result); return test_result; } -static int cleanup_bgp_info_mpath_update(testcase_t *t) +static int cleanup_bgp_path_info_mpath_update(testcase_t *t) { int i; @@ -353,11 +355,11 @@ static int cleanup_bgp_info_mpath_update(testcase_t *t) return 0; } -testcase_t test_bgp_info_mpath_update = { - .desc = "Test bgp_info_mpath_update", - .setup = setup_bgp_info_mpath_update, - .run = run_bgp_info_mpath_update, - .cleanup = cleanup_bgp_info_mpath_update, +testcase_t test_bgp_path_info_mpath_update = { + .desc = "Test bgp_path_info_mpath_update", + .setup = setup_bgp_path_info_mpath_update, + .run = run_bgp_path_info_mpath_update, + .cleanup = cleanup_bgp_path_info_mpath_update, }; /*========================================================= @@ -365,7 +367,7 @@ testcase_t test_bgp_info_mpath_update = { */ testcase_t *all_tests[] = { &test_bgp_cfg_maximum_paths, &test_bgp_mp_list, - &test_bgp_info_mpath_update, + &test_bgp_path_info_mpath_update, }; int all_tests_count = (sizeof(all_tests) / sizeof(testcase_t *)); diff --git a/tests/bgpd/test_mpath.py b/tests/bgpd/test_mpath.py index 3024669507..ce34ff8436 100644 --- a/tests/bgpd/test_mpath.py +++ b/tests/bgpd/test_mpath.py @@ -5,5 +5,5 @@ class TestMpath(frrtest.TestMultiOut): TestMpath.okfail("bgp maximum-paths config") TestMpath.okfail("bgp_mp_list") -TestMpath.okfail("bgp_info_mpath_update") +TestMpath.okfail("bgp_path_info_mpath_update") 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/tests/subdir.am b/tests/subdir.am index 739a0e86fe..a4a754b088 100644 --- a/tests/subdir.am +++ b/tests/subdir.am @@ -84,6 +84,7 @@ tests/lib/cli/test_commands_defun.c: vtysh/vtysh_cmd.c -e 's/VTYSH_[A-Z][A-Z_0-9]*/0/g' \ < vtysh/vtysh_cmd.c \ > "$@" +CLEANFILES += tests/lib/cli/test_commands_defun.c tests/isisd/test_fuzz_isis_tlv_tests.h: $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz gzip -d < $(top_srcdir)/tests/isisd/test_fuzz_isis_tlv_tests.h.gz > "$@" @@ -166,7 +167,8 @@ tests_lib_cli_test_cli_SOURCES = tests/lib/cli/test_cli.c tests/lib/cli/common_c tests_lib_cli_test_commands_CFLAGS = $(TESTS_CFLAGS) tests_lib_cli_test_commands_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_cli_test_commands_LDADD = $(ALL_TESTS_LDADD) -tests_lib_cli_test_commands_SOURCES = tests/lib/cli/test_commands_defun.c tests/lib/cli/test_commands.c tests/helpers/c/prng.c +nodist_tests_lib_cli_test_commands_SOURCES = tests/lib/cli/test_commands_defun.c +tests_lib_cli_test_commands_SOURCES = tests/lib/cli/test_commands.c tests/helpers/c/prng.c tests_lib_test_buffer_CFLAGS = $(TESTS_CFLAGS) tests_lib_test_buffer_CPPFLAGS = $(TESTS_CPPFLAGS) tests_lib_test_buffer_LDADD = $(ALL_TESTS_LDADD) @@ -293,3 +295,8 @@ EXTRA_DIST += \ tests/tests.xml: $(check_PROGRAMS) ( cd tests; $(PYTHON) ../$(srcdir)/tests/runtests.py --junitxml=tests.xml -v ../$(srcdir)/tests; ) check: tests/tests.xml + +clean-local: clean-tests +.PHONY: clean-tests +clean-tests: + -rm -f tests/tests.xml diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons index 474b299d90..1514082e90 100644 --- a/tools/etc/frr/daemons +++ b/tools/etc/frr/daemons @@ -36,3 +36,4 @@ babeld=no sharpd=no pbrd=no bfdd=no +fabricd=no diff --git a/tools/etc/frr/daemons.conf b/tools/etc/frr/daemons.conf index 640437f441..bd0e370d1e 100644 --- a/tools/etc/frr/daemons.conf +++ b/tools/etc/frr/daemons.conf @@ -20,6 +20,7 @@ sharpd_options=" --daemon -A 127.0.0.1" pbrd_options=" --daemon -A 127.0.0.1" staticd_options=" --daemon -A 127.0.0.1" bfdd_options=" --daemon -A 127.0.0.1" +fabricd_options=" --daemon -A 127.0.0.1" # The list of daemons to watch is automatically generated by the init script. watchfrr_enable=yes diff --git a/tools/etc/rsyslog.d/45-frr.conf b/tools/etc/rsyslog.d/45-frr.conf index ff7cd48318..4612e8beaf 100644 --- a/tools/etc/rsyslog.d/45-frr.conf +++ b/tools/etc/rsyslog.d/45-frr.conf @@ -8,6 +8,7 @@ if $programname == 'babeld' or $programname == 'eigrpd' or $programname == 'frr' or $programname == 'isisd' or + $programname == 'fabricd' or $programname == 'ldpd' or $programname == 'nhrpd' or $programname == 'ospf6d' or @@ -24,6 +25,7 @@ if $programname == 'babeld' or $programname == 'eigrpd' or $programname == 'frr' or $programname == 'isisd' or + $programname == 'fabricd' or $programname == 'ldpd' or $programname == 'nhrpd' or $programname == 'ospf6d' or diff --git a/tools/frr.in b/tools/frr.in index 4ff080909d..ee8dc883dc 100755 --- a/tools/frr.in +++ b/tools/frr.in @@ -25,57 +25,57 @@ FRR_VTY_GROUP="@enable_vty_group@" # frrvty # Local Daemon selection may be done by using /etc/frr/daemons. # See /usr/share/doc/frr/README.Debian.gz for further information. # Keep zebra first and do not list watchfrr! -DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd" +DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd" MAX_INSTANCES=5 RELOAD_SCRIPT="$D_PATH/frr-reload.py" if [ -e /lib/lsb/init-functions ]; then - . /lib/lsb/init-functions + . /lib/lsb/init-functions fi if [ -f $D_PATH/ssd ]; then - SSD=$D_PATH/ssd + SSD=$D_PATH/ssd else - SSD=`which start-stop-daemon` + SSD=`which start-stop-daemon` fi # Print the name of the pidfile. pidfile() { - echo "$V_PATH/$1.pid" + echo "$V_PATH/$1.pid" } # Print the name of the vtysh. vtyfile() { - echo "$V_PATH/$1.vty" + echo "$V_PATH/$1.vty" } chownfrr() { - test -n "$FRR_USER" && chown "$FRR_USER" "$1" - test -n "$FRR_GROUP" && chgrp "$FRR_GROUP" "$1" + test -n "$FRR_USER" && chown "$FRR_USER" "$1" + test -n "$FRR_GROUP" && chgrp "$FRR_GROUP" "$1" } # Check if daemon is started by using the pidfile. started() { - [ ! -e `pidfile $1` ] && return 3 - if [ -n "$2" ] && [ "$2" == "log" ]; then - status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $? - else - kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1 - return 0 - fi + [ ! -e `pidfile $1` ] && return 3 + if [ -n "$2" ] && [ "$2" == "log" ]; then + status_of_proc -p `pidfile $1` $1 $1 && return 0 || return $? + else + kill -0 `cat \`pidfile $1\`` 2> /dev/null || return 1 + return 0 + fi } # Loads the config via vtysh -b if configured to do so. vtysh_b () { - # Rember, that all variables have been incremented by 1 in convert_daemon_prios() - if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then - $VTYSH -b -n - fi + # Rember, that all variables have been incremented by 1 in convert_daemon_prios() + if [ "$vtysh_enable" = 2 -a -f $C_PATH/frr.conf ]; then + $VTYSH -b -n + fi } # Check if the daemon is activated and if its executable and config files @@ -84,421 +84,421 @@ vtysh_b () # returns: 0=ok, 1=error check_daemon() { - if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then - # check for daemon binary - if [ ! -x "$D_PATH/$1" ]; then return 1; fi - fi + if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then + # check for daemon binary + if [ ! -x "$D_PATH/$1" ]; then return 1; fi + fi - # If the integrated config file is used the others are not checked. - if [ -r "$C_PATH/frr.conf" ]; then - return 0 - fi + # If the integrated config file is used the others are not checked. + if [ -r "$C_PATH/frr.conf" ]; then + return 0 + fi - # vtysh_enable has no config file nor binary so skip check. - # (Not sure why vtysh_enable is in this list but does not hurt) - if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then - # check for config file - if [ -n "$2" ]; then - if [ ! -r "$C_PATH/$1-$2.conf" ]; then - touch "$C_PATH/$1-$2.conf" - chownfrr "$C_PATH/$1-$2.conf" - fi - elif [ ! -r "$C_PATH/$1.conf" ]; then - touch "$C_PATH/$1.conf" - chownfrr "$C_PATH/$1.conf" - fi - fi - return 0 + # vtysh_enable has no config file nor binary so skip check. + # (Not sure why vtysh_enable is in this list but does not hurt) + if [ $1 != "watchfrr" -a $1 != "vtysh_enable" ]; then + # check for config file + if [ -n "$2" ]; then + if [ ! -r "$C_PATH/$1-$2.conf" ]; then + touch "$C_PATH/$1-$2.conf" + chownfrr "$C_PATH/$1-$2.conf" + fi + elif [ ! -r "$C_PATH/$1.conf" ]; then + touch "$C_PATH/$1.conf" + chownfrr "$C_PATH/$1.conf" + fi + fi + return 0 } # Starts the server if it's not alrady running according to the pid file. # The Frr daemons creates the pidfile when starting. start() { - ulimit -n $MAX_FDS - if [ "$1" = "watchfrr" ]; then + ulimit -n $MAX_FDS + if [ "$1" = "watchfrr" ]; then - # We may need to restart watchfrr if new daemons are added and/or - # removed - if started "$1" ; then - stop watchfrr - else - # Echo only once. watchfrr is printed in the stop above - echo -n " $1" - fi + # We may need to restart watchfrr if new daemons are added and/or + # removed + if started "$1" ; then + stop watchfrr + else + # Echo only once. watchfrr is printed in the stop above + echo -n " $1" + fi - ${SSD} \ - --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ - -- \ - "${watchfrr_options[@]}" + ${SSD} \ + --start \ + --pidfile=`pidfile $1` \ + --exec "$D_PATH/$1" \ + -- \ + "${watchfrr_options[@]}" - elif [ -n "$2" ]; then - echo -n " $1-$2" - if ! check_daemon $1 $2 ; then - echo -n " (binary does not exist)" - return; - fi + elif [ -n "$2" ]; then + echo -n " $1-$2" + if ! check_daemon $1 $2 ; then + echo -n " (binary does not exist)" + return; + fi - ${SSD} \ - --start \ - --pidfile=`pidfile $1-$2` \ - --exec "$D_PATH/$1" \ - -- \ - `eval echo "$""$1""_options"` -n "$2" - else - echo -n " $1" - if ! check_daemon $1; then - echo -n " (binary does not exist)" - return; - fi + ${SSD} \ + --start \ + --pidfile=`pidfile $1-$2` \ + --exec "$D_PATH/$1" \ + -- \ + `eval echo "$""$1""_options"` -n "$2" + else + echo -n " $1" + if ! check_daemon $1; then + echo -n " (binary does not exist)" + return; + fi - if [ "$valgrind_enable" = "yes" ]; then - ${SSD} \ - --start \ - --pidfile=`pidfile $1` \ - --exec "$valgrind" \ - -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$1-valgrind.log $D_PATH/$1 \ - `eval echo "$""$1""_options"` - else - ${SSD} \ - --start \ - --pidfile=`pidfile $1` \ - --exec "$D_PATH/$1" \ - -- \ - `eval echo "$""$1""_options"` - fi - fi + if [ "$valgrind_enable" = "yes" ]; then + ${SSD} \ + --start \ + --pidfile=`pidfile $1` \ + --exec "$valgrind" \ + -- --trace-children=no --leak-check=full --log-file=/var/log/frr/$1-valgrind.log $D_PATH/$1 \ + `eval echo "$""$1""_options"` + else + ${SSD} \ + --start \ + --pidfile=`pidfile $1` \ + --exec "$D_PATH/$1" \ + -- \ + `eval echo "$""$1""_options"` + fi + fi # Start the staticd automatically if [ "$1" = "zebra" ]; then - echo -n "starting staticd since zebra is running" - if ! check_daemon staticd ; then - echo -n " (binary does not exist)" - return; - fi + echo -n "starting staticd since zebra is running" + if ! check_daemon staticd ; then + echo -n " (binary does not exist)" + return; + fi - ${SSD} \ - --start \ - --pidfile=`pidfile staticd` \ - --exec "$D_PATH/staticd" \ - -- \ - `eval echo "$"staticd"_options"` + ${SSD} \ + --start \ + --pidfile=`pidfile staticd` \ + --exec "$D_PATH/staticd" \ + -- \ + `eval echo "$"staticd"_options"` fi } # Stop the daemon given in the parameter, printing its name to the terminal. stop() { - local inst + local inst - if [ -n "$2" ]; then - inst="$1-$2" - else - inst="$1" - fi - - if ! started "$inst" ; then - echo -n " ($inst)" - return 0 - else - PIDFILE=`pidfile $inst` - PID=`cat $PIDFILE 2>/dev/null` - kill -2 $PID 2>/dev/null - # - # Now we have to wait until $DAEMON has _really_ stopped. - # - if test -n "$PID" && kill -0 $PID 2>/dev/null; then - echo -n " (waiting) ." - cnt=0 - while kill -0 $PID 2>/dev/null; do - cnt=`expr $cnt + 1` - if [ $cnt -gt 60 ]; then - # Waited 120 secs now, fail. - echo -n "Failed.. " - break - fi - sleep 2 - echo -n "." - done - fi - echo -n " $inst" - rm -f `pidfile $inst` - rm -f `vtyfile $inst` - - if [ "$1" = "zebra" ]; then - echo -n "Stopping staticd since zebra is running" - stop staticd + if [ -n "$2" ]; then + inst="$1-$2" + else + inst="$1" + fi + + if ! started "$inst" ; then + echo -n " ($inst)" + return 0 + else + PIDFILE=`pidfile $inst` + PID=`cat $PIDFILE 2>/dev/null` + kill -2 $PID 2>/dev/null + # + # Now we have to wait until $DAEMON has _really_ stopped. + # + if test -n "$PID" && kill -0 $PID 2>/dev/null; then + echo -n " (waiting) ." + cnt=0 + while kill -0 $PID 2>/dev/null; do + cnt=`expr $cnt + 1` + if [ $cnt -gt 60 ]; then + # Waited 120 secs now, fail. + echo -n "Failed.. " + break + fi + sleep 2 + echo -n "." + done + fi + echo -n " $inst" + rm -f `pidfile $inst` + rm -f `vtyfile $inst` + + if [ "$1" = "zebra" ]; then + echo -n "Stopping staticd since zebra is running" + stop staticd + fi fi - fi } # Converts values from /etc/frr/daemons to all-numeric values. convert_daemon_prios() { - for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do - # First, assign the value set by the user to $value - eval value=\${${name}:0:3} + for name in $DAEMONS zebra vtysh_enable watchfrr_enable; do + # First, assign the value set by the user to $value + eval value=\${${name}:0:3} - # Daemon not activated or entry missing? - if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi + # Daemon not activated or entry missing? + if [ "$value" = "no" -o "$value" = "" ]; then value=0; fi - # These strings parsed for backwards compatibility. - if [ "$value" = "yes" -o "$value" = "true" ]; then - value=1; - fi + # These strings parsed for backwards compatibility. + if [ "$value" = "yes" -o "$value" = "true" ]; then + value=1; + fi - # Zebra is threatened special. It must be between 0=off and the first - # user assigned value "1" so we increase all other enabled daemons' values. - if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi + # Zebra is threatened special. It must be between 0=off and the first + # user assigned value "1" so we increase all other enabled daemons' values. + if [ "$name" != "zebra" -a "$value" -gt 0 ]; then value=`expr "$value" + 1`; fi - # If e.g. name is zebra then we set "zebra=yes". - eval $name=$value - done + # If e.g. name is zebra then we set "zebra=yes". + eval $name=$value + done } # Starts watchfrr for all wanted daemons. start_watchfrr() { - local daemon_name - local daemon_prio - local found_one - local daemon_inst + local daemon_name + local daemon_prio + local found_one + local daemon_inst - # Start the monitor daemon only if desired. - if [ 0 -eq "$watchfrr_enable" ]; then - return - fi + # Start the monitor daemon only if desired. + if [ 0 -eq "$watchfrr_enable" ]; then + return + fi - # Check variable type - if ! declare -p watchfrr_options | grep -q '^declare \-a'; then - echo - echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!" - echo "ERROR: Please convert config file and restart!" - exit 1 - fi + # Check variable type + if ! declare -p watchfrr_options | grep -q '^declare \-a'; then + echo + echo "ERROR: The variable watchfrr_options from /etc/frr/debian.cnf must be a BASH array!" + echo "ERROR: Please convert config file and restart!" + exit 1 + fi - # Which daemons have been started? - found_one=0 - for daemon_name in $DAEMONS; do - eval daemon_prio=\$$daemon_name - if [ "$daemon_prio" -gt 0 ]; then - eval "daemon_inst=\${${daemon_name}_instances//,/ }" - if [ -n "$daemon_inst" ]; then - for inst in ${daemon_inst}; do - eval "inst_disable=\${${daemon_name}_${inst}}" - if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then - if check_daemon $daemon_name $inst; then - watchfrr_options+=("${daemon_name}-${inst}") - fi - fi - done - else - if check_daemon $daemon_name; then - watchfrr_options+=($daemon_name) - fi - fi - found_one=1 - fi - done + # Which daemons have been started? + found_one=0 + for daemon_name in $DAEMONS; do + eval daemon_prio=\$$daemon_name + if [ "$daemon_prio" -gt 0 ]; then + eval "daemon_inst=\${${daemon_name}_instances//,/ }" + if [ -n "$daemon_inst" ]; then + for inst in ${daemon_inst}; do + eval "inst_disable=\${${daemon_name}_${inst}}" + if [ -z ${inst_disable} ] || [ ${inst_disable} != 0 ]; then + if check_daemon $daemon_name $inst; then + watchfrr_options+=("${daemon_name}-${inst}") + fi + fi + done + else + if check_daemon $daemon_name; then + watchfrr_options+=($daemon_name) + fi + fi + found_one=1 + fi + done - # Start if at least one daemon is activated. - if [ $found_one -eq 1 ]; then - echo -n "Starting Frr monitor daemon:" - start watchfrr - echo "." - fi + # Start if at least one daemon is activated. + if [ $found_one -eq 1 ]; then + echo -n "Starting Frr monitor daemon:" + start watchfrr + echo "." + fi } # Stopps watchfrr. stop_watchfrr() { - echo -n "Stopping Frr monitor daemon:" - stop watchfrr - echo "." + echo -n "Stopping Frr monitor daemon:" + stop watchfrr + echo "." } # Stops all daemons that have a lower level of priority than the given. # (technically if daemon_prio >= wanted_prio) stop_prio() { - local wanted_prio - local daemon_prio - local daemon_list - local daemon_inst - local inst + local wanted_prio + local daemon_prio + local daemon_list + local daemon_inst + local inst - if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then - daemon=${BASH_REMATCH[1]} - inst=${BASH_REMATCH[2]} - else - daemon="$2" - fi + if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then + daemon=${BASH_REMATCH[1]} + inst=${BASH_REMATCH[2]} + else + daemon="$2" + fi - wanted_prio=$1 - daemon_list=${daemon:-$DAEMONS} + wanted_prio=$1 + daemon_list=${daemon:-$DAEMONS} - echo -n "Stopping Frr daemons (prio:$wanted_prio):" + echo -n "Stopping Frr daemons (prio:$wanted_prio):" - for prio_i in `seq 10 -1 $wanted_prio`; do - for daemon_name in $daemon_list; do - eval daemon_prio=\${${daemon_name}:0:3} - daemon_inst="" - if [ $daemon_prio -eq $prio_i ]; then - eval "daemon_inst=\${${daemon_name}_instances//,/ }" - if [ -n "$daemon_inst" ]; then - for i in ${daemon_inst}; do - if [ -n "$inst" ] && [ "$i" == "$inst" ]; then - stop "$daemon_name" "$inst" - elif [ x"$inst" == x ]; then - stop "$daemon_name" "$i" - fi - done - else - stop "$daemon_name" - fi - fi - done - done + for prio_i in `seq 10 -1 $wanted_prio`; do + for daemon_name in $daemon_list; do + eval daemon_prio=\${${daemon_name}:0:3} + daemon_inst="" + if [ $daemon_prio -eq $prio_i ]; then + eval "daemon_inst=\${${daemon_name}_instances//,/ }" + if [ -n "$daemon_inst" ]; then + for i in ${daemon_inst}; do + if [ -n "$inst" ] && [ "$i" == "$inst" ]; then + stop "$daemon_name" "$inst" + elif [ x"$inst" == x ]; then + stop "$daemon_name" "$i" + fi + done + else + stop "$daemon_name" + fi + fi + done + done - echo "." - if [ -z "$inst" ]; then - # Now stop other daemons that're prowling, coz the daemons file changed - echo -n "Stopping other frr daemons" - if [ -n "$daemon" ]; then - eval "file_list_suffix="$V_PATH"/"$daemon*"" - else - eval "file_list_suffix="$V_PATH/*"" - fi - for pidfile in $file_list_suffix.pid; do - PID=`cat $pidfile 2>/dev/null` - ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" - echo -n "." - rm -rf "$pidfile" - done - echo "." + echo "." + if [ -z "$inst" ]; then + # Now stop other daemons that're prowling, coz the daemons file changed + echo -n "Stopping other frr daemons" + if [ -n "$daemon" ]; then + eval "file_list_suffix="$V_PATH"/"$daemon*"" + else + eval "file_list_suffix="$V_PATH/*"" + fi + for pidfile in $file_list_suffix.pid; do + PID=`cat $pidfile 2>/dev/null` + ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" + echo -n "." + rm -rf "$pidfile" + done + echo "." - echo -n "Removing remaining .vty files" - for vtyfile in $file_list_suffix.vty; do - rm -rf "$vtyfile" - done - echo "." - fi + echo -n "Removing remaining .vty files" + for vtyfile in $file_list_suffix.vty; do + rm -rf "$vtyfile" + done + echo "." + fi } # Starts all daemons that have a higher level of priority than the given. # (technically if daemon_prio <= wanted_prio) start_prio() { - local wanted_prio - local daemon_prio - local daemon_list - local daemon_name - local daemon_inst - local inst + local wanted_prio + local daemon_prio + local daemon_list + local daemon_name + local daemon_inst + local inst - if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then - daemon=${BASH_REMATCH[1]} - inst=${BASH_REMATCH[2]} - else - daemon="$2" - fi + if [ -n "$2" ] && [[ "$2" =~ (.*)-(.*) ]]; then + daemon=${BASH_REMATCH[1]} + inst=${BASH_REMATCH[2]} + else + daemon="$2" + fi - wanted_prio=$1 - daemon_list=${daemon:-$DAEMONS} + wanted_prio=$1 + daemon_list=${daemon:-$DAEMONS} - echo -n "Starting Frr daemons (prio:$wanted_prio):" + echo -n "Starting Frr daemons (prio:$wanted_prio):" - for prio_i in `seq 1 $wanted_prio`; do - for daemon_name in $daemon_list; do - eval daemon_prio=\$${daemon_name} - daemon_inst="" - if [ $daemon_prio -eq $prio_i ]; then - eval "daemon_inst=\${${daemon_name}_instances//,/ }" - if [ -n "$daemon_inst" ]; then - if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then - echo "Max instances supported is ${MAX_INSTANCES}. Aborting" - exit 1 - fi - # Check if we're starting again by switching from single instance - # to MI version - if started "$daemon_name"; then - PIDFILE=`pidfile $daemon_name` - ${SSD} \ - --stop --quiet --oknodo \ - --pidfile "$PIDFILE" \ - --exec "$D_PATH/$daemon_name" + for prio_i in `seq 1 $wanted_prio`; do + for daemon_name in $daemon_list; do + eval daemon_prio=\$${daemon_name} + daemon_inst="" + if [ $daemon_prio -eq $prio_i ]; then + eval "daemon_inst=\${${daemon_name}_instances//,/ }" + if [ -n "$daemon_inst" ]; then + if [ `echo "$daemon_inst" | wc -w` -gt ${MAX_INSTANCES} ]; then + echo "Max instances supported is ${MAX_INSTANCES}. Aborting" + exit 1 + fi + # Check if we're starting again by switching from single instance + # to MI version + if started "$daemon_name"; then + PIDFILE=`pidfile $daemon_name` + ${SSD} \ + --stop --quiet --oknodo \ + --pidfile "$PIDFILE" \ + --exec "$D_PATH/$daemon_name" - rm -f `pidfile $1` - rm -f `vtyfile $1` - fi + rm -f `pidfile $1` + rm -f `vtyfile $1` + fi - for i in ${daemon_inst}; do - if [ -n "$inst" ] && [ "$i" == "$inst" ]; then - start "$daemon_name" "$inst" - elif [ x"$inst" == x ]; then - start "$daemon_name" "$i" - fi - done - else - # Check if we're starting again by switching from - # single instance to MI version - eval "file_list_suffix="$V_PATH"/"$daemon_name-*"" - for pidfile in $file_list_suffix.pid; do - ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" - echo -n "." - rm -rf "$pidfile" - done - for vtyfile in $file_list_suffix.vty; do - rm -rf "$vtyfile" - done + for i in ${daemon_inst}; do + if [ -n "$inst" ] && [ "$i" == "$inst" ]; then + start "$daemon_name" "$inst" + elif [ x"$inst" == x ]; then + start "$daemon_name" "$i" + fi + done + else + # Check if we're starting again by switching from + # single instance to MI version + eval "file_list_suffix="$V_PATH"/"$daemon_name-*"" + for pidfile in $file_list_suffix.pid; do + ${SSD} --stop --quiet --oknodo --pidfile "$pidfile" + echo -n "." + rm -rf "$pidfile" + done + for vtyfile in $file_list_suffix.vty; do + rm -rf "$vtyfile" + done - start "$daemon_name" - fi - fi - done - done - echo "." + start "$daemon_name" + fi + fi + done + done + echo "." } check_status() { - local daemon_name - local daemon_prio - local daemon_inst - local failed_status=0 + local daemon_name + local daemon_prio + local daemon_inst + local failed_status=0 - if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then - daemon=${BASH_REMATCH[1]} - inst=${BASH_REMATCH[2]} - else - daemon="$1" - fi + if [ -n "$1" ] && [[ "$1" =~ (.*)-(.*) ]]; then + daemon=${BASH_REMATCH[1]} + inst=${BASH_REMATCH[2]} + else + daemon="$1" + fi - daemon_list=${daemon:-$DAEMONS} + daemon_list=${daemon:-$DAEMONS} - # Which daemons have been started? - for daemon_name in $daemon_list; do - eval daemon_prio=\$$daemon_name - if [ "$daemon_prio" -gt 0 ]; then - eval "daemon_inst=\${${daemon_name}_instances//,/ }" - if [ -n "$daemon_inst" ]; then - for i in ${daemon_inst}; do - if [ -n "$inst" -a "$inst" = "$i" ]; then - started "$1" "log" || failed_status=$? - elif [ -z "$inst" ]; then - started "$daemon_name-$i" "log" || failed_status=$? - fi - done - else - started "$daemon_name" "log" || failed_status=$? - fi - fi - done + # Which daemons have been started? + for daemon_name in $daemon_list; do + eval daemon_prio=\$$daemon_name + if [ "$daemon_prio" -gt 0 ]; then + eval "daemon_inst=\${${daemon_name}_instances//,/ }" + if [ -n "$daemon_inst" ]; then + for i in ${daemon_inst}; do + if [ -n "$inst" -a "$inst" = "$i" ]; then + started "$1" "log" || failed_status=$? + elif [ -z "$inst" ]; then + started "$daemon_name-$i" "log" || failed_status=$? + fi + done + else + started "$daemon_name" "log" || failed_status=$? + fi + fi + done - # All daemons that need to have been started are up and running - return $failed_status + # All daemons that need to have been started are up and running + return $failed_status } ######################################################### @@ -521,112 +521,112 @@ MAX_INSTANCES=${MAX_INSTANCES:=5} convert_daemon_prios if [ ! -d $V_PATH ]; then - echo "Creating $V_PATH" - mkdir -p $V_PATH - chownfrr $V_PATH - chmod 755 /$V_PATH + echo "Creating $V_PATH" + mkdir -p $V_PATH + chownfrr $V_PATH + chmod 755 /$V_PATH fi if [ -n "$3" ] && [ "$3" != "all" ]; then - dmn="$2"-"$3" + dmn="$2"-"$3" elif [ -n "$2" ] && [ "$2" != "all" ]; then - dmn="$2" + dmn="$2" fi case "$1" in - start) - # Try to load this necessary (at least for 2.6) module. - if [ -d /lib/modules/`uname -r` ] ; then - echo "Loading capability module if not yet done." - set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e - fi + start) + # Try to load this necessary (at least for 2.6) module. + if [ -d /lib/modules/`uname -r` ] ; then + echo "Loading capability module if not yet done." + set +e; LC_ALL=C modprobe -a capability 2>&1 | egrep -v "(not found|Can't locate)"; set -e + fi - # Start all daemons - cd $C_PATH/ - if [ "$2" != "watchfrr" ]; then - start_prio 10 $dmn - fi - start_watchfrr - vtysh_b - ;; + # Start all daemons + cd $C_PATH/ + if [ "$2" != "watchfrr" ]; then + start_prio 10 $dmn + fi + start_watchfrr + vtysh_b + ;; - 1|2|3|4|5|6|7|8|9|10) - # Stop/start daemons for the appropriate priority level - stop_prio $1 - start_prio $1 - vtysh_b - ;; + 1|2|3|4|5|6|7|8|9|10) + # Stop/start daemons for the appropriate priority level + stop_prio $1 + start_prio $1 + vtysh_b + ;; - stop|0) - # Stop all daemons at level '0' or 'stop' - stop_watchfrr - if [ "$dmn" != "watchfrr" ]; then - [ -n "${dmn}" ] && eval "${dmn/-/_}=0" - stop_prio 0 $dmn - fi + stop|0) + # Stop all daemons at level '0' or 'stop' + stop_watchfrr + if [ "$dmn" != "watchfrr" ]; then + [ -n "${dmn}" ] && eval "${dmn/-/_}=0" + stop_prio 0 $dmn + fi - if [ -z "$dmn" -o "$dmn" = "zebra" ]; then - echo "Removing all routes made by FRR." - # Specific values for each proto can be found - # in /etc/iproute2/rt_protos as well as FRR - # specific ones in /etc/iproute2/rt_protos.d - # Additionally if a new protocol is added - # we need to add it here as well as - # in rt_netlink.h( follow the directions! ) - ip route flush proto 4 - ip route flush proto 11 - ip route flush proto 42 - ip route flush proto 186 - ip route flush proto 187 - ip route flush proto 188 - ip route flush proto 189 - ip route flush proto 190 - ip route flush proto 191 - ip route flush proto 192 - ip route flush proto 193 - ip route flush proto 194 - ip route flush proto 195 - ip route flush proto 196 - ip route flush proto 197 - else - [ -n "$dmn" ] && eval "${dmn/-/_}=0" - start_watchfrr - fi - ;; + if [ -z "$dmn" -o "$dmn" = "zebra" ]; then + echo "Removing all routes made by FRR." + # Specific values for each proto can be found + # in /etc/iproute2/rt_protos as well as FRR + # specific ones in /etc/iproute2/rt_protos.d + # Additionally if a new protocol is added + # we need to add it here as well as + # in rt_netlink.h( follow the directions! ) + ip route flush proto 4 + ip route flush proto 11 + ip route flush proto 42 + ip route flush proto 186 + ip route flush proto 187 + ip route flush proto 188 + ip route flush proto 189 + ip route flush proto 190 + ip route flush proto 191 + ip route flush proto 192 + ip route flush proto 193 + ip route flush proto 194 + ip route flush proto 195 + ip route flush proto 196 + ip route flush proto 197 + else + [ -n "$dmn" ] && eval "${dmn/-/_}=0" + start_watchfrr + fi + ;; - reload) - # Just apply the commands that have changed, no restart necessary - if [ ! -x "$RELOAD_SCRIPT" ]; then - echo "Please install frr-pythontools package. Required for reload" - exit 0 - fi + reload) + # Just apply the commands that have changed, no restart necessary + if [ ! -x "$RELOAD_SCRIPT" ]; then + echo "Please install frr-pythontools package. Required for reload" + exit 0 + fi - NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}" - [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1 - echo "Applying only incremental changes to running configuration from frr.conf" - "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf - exit $? - ;; + NEW_CONFIG_FILE="${2:-$C_PATH/frr.conf}" + [ ! -r $NEW_CONFIG_FILE ] && echo "Unable to read new configuration file $NEW_CONFIG_FILE" && exit 1 + echo "Applying only incremental changes to running configuration from frr.conf" + "$RELOAD_SCRIPT" --reload $C_PATH/frr.conf + exit $? + ;; - status) - check_status $dmn - exit $? - ;; + status) + check_status $dmn + exit $? + ;; - restart|force-reload) - $0 stop $dmn - sleep 1 - $0 start $dmn - ;; + restart|force-reload) + $0 stop $dmn + sleep 1 + $0 start $dmn + ;; - *) - echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|} [daemon]" - echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5." - echo " reload applies only modifications from the running config to all daemons." - echo " reload neither restarts starts any daemon nor starts any new ones." - echo " Read /usr/share/doc/frr/README.Debian for details." - exit 1 - ;; + *) + echo "Usage: /etc/init.d/frr {start|stop|status|reload|restart|force-reload|} [daemon]" + echo " E.g. '/etc/init.d/frr 5' would start all daemons with a prio 1-5." + echo " reload applies only modifications from the running config to all daemons." + echo " reload neither restarts starts any daemon nor starts any new ones." + echo " Read /usr/share/doc/frr/README.Debian for details." + exit 1 + ;; esac echo "Exiting from the script" diff --git a/tools/start-stop-daemon.c b/tools/start-stop-daemon.c index 8daeda7402..f2a1e9434b 100644 --- a/tools/start-stop-daemon.c +++ b/tools/start-stop-daemon.c @@ -1013,7 +1013,7 @@ int main(int argc, char **argv) if (background) { /* ok, we need to detach this process */ int i, fd; if (quietmode < 0) - printf("Detatching to start %s...", startas); + printf("Detaching to start %s...", startas); i = fork(); if (i < 0) { fatal("Unable to fork.\n"); diff --git a/tools/subdir.am b/tools/subdir.am index 323d1222f9..f8a14d10cc 100644 --- a/tools/subdir.am +++ b/tools/subdir.am @@ -17,7 +17,6 @@ tools_ssd_SOURCES = tools/start-stop-daemon.c EXTRA_DIST += \ tools/etc \ - tools/frr \ tools/frr-reload \ tools/frr-reload.py \ tools/frr.service \ diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in index 0f68e58d62..596f01738a 100755 --- a/vtysh/extract.pl.in +++ b/vtysh/extract.pl.in @@ -85,7 +85,7 @@ sub scan_file { # $protocol is VTYSH_PROTO format for redirection of user input if ($file =~ /lib\/keychain\.c$/) { - $protocol = "VTYSH_RIPD"; + $protocol = "VTYSH_RIPD|VTYSH_EIGRPD"; } elsif ($file =~ /lib\/routemap\.c$/) { $protocol = "VTYSH_RMAP"; diff --git a/vtysh/subdir.am b/vtysh/subdir.am index 932429a87c..c9cdb58543 100644 --- a/vtysh/subdir.am +++ b/vtysh/subdir.am @@ -24,9 +24,7 @@ noinst_HEADERS += \ vtysh/vtysh_user.h \ # end -vtysh_vtysh_LDADD = lib/libfrr.la @LIBCAP@ @LIBREADLINE@ @LIBS@ @CURSES@ @LIBPAM@ - -EXTRA_DIST += vtysh/extract.pl +vtysh_vtysh_LDADD = lib/libfrr.la @LIBCAP@ @LIBREADLINE@ @LIBS@ @LIBPAM@ AM_V_EXTRACT = $(am__v_EXTRACT_$(V)) am__v_EXTRACT_ = $(am__v_EXTRACT_$(AM_DEFAULT_VERBOSITY)) diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c index 6a92b90813..35f719fa54 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: @@ -1502,7 +1502,7 @@ DEFUNSH(VTYSH_BGPD, vnc_l2_group, vnc_l2_group_cmd, "vnc l2-group NAME", } #endif -DEFUNSH(VTYSH_RIPD, key_chain, key_chain_cmd, "key chain WORD", +DEFUNSH(VTYSH_KEYS, key_chain, key_chain_cmd, "key chain WORD", "Authentication key management\n" "Key-chain management\n" "Key-chain name\n") @@ -1511,7 +1511,7 @@ DEFUNSH(VTYSH_RIPD, key_chain, key_chain_cmd, "key chain WORD", return CMD_SUCCESS; } -DEFUNSH(VTYSH_RIPD, key, key_cmd, "key (0-2147483647)", +DEFUNSH(VTYSH_KEYS, key, key_cmd, "key (0-2147483647)", "Configure a key\n" "Key identifier number\n") { @@ -2265,7 +2265,7 @@ DEFUN (vtysh_show_work_queues, DEFUN (vtysh_show_work_queues_daemon, vtysh_show_work_queues_daemon_cmd, - "show work-queues ", + "show work-queues ", SHOW_STR "Work Queue information\n" "For the zebra daemon\n" @@ -2276,7 +2276,9 @@ DEFUN (vtysh_show_work_queues_daemon, "For the bgp daemon\n" "For the isis daemon\n" "For the pbr daemon\n" - "For the fabricd daemon\n") + "For the fabricd daemon\n" + "For the pim daemon\n" + "For the static daemon\n") { int idx_protocol = 2; unsigned int i; @@ -2614,7 +2616,7 @@ DEFUNSH(VTYSH_ALL, no_vtysh_config_enable_password, DEFUN (vtysh_write_terminal, vtysh_write_terminal_cmd, - "write terminal []", + "write terminal []", "Write running configuration to memory, network, or terminal\n" "Write to terminal\n" "For the zebra daemon\n" @@ -2626,7 +2628,8 @@ DEFUN (vtysh_write_terminal, "For the bgp daemon\n" "For the isis daemon\n" "For the fabricd daemon\n" - "For the pim daemon\n") + "For the pim daemon\n" + "For the static daemon\n") { unsigned int i; char line[] = "do write terminal\n"; @@ -2652,7 +2655,7 @@ DEFUN (vtysh_write_terminal, DEFUN (vtysh_show_running_config, vtysh_show_running_config_cmd, - "show running-config []", + "show running-config []", SHOW_STR "Current operating configuration\n" "For the zebra daemon\n" @@ -2664,7 +2667,8 @@ DEFUN (vtysh_show_running_config, "For the bgp daemon\n" "For the isis daemon\n" "For the fabricd daemon\n" - "For the pim daemon\n") + "For the pim daemon\n" + "For the static daemon\n") { return vtysh_write_terminal(self, vty, argc, argv); } diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h index ee980d5128..430b117c50 100644 --- a/vtysh/vtysh.h +++ b/vtysh/vtysh.h @@ -55,6 +55,7 @@ DECLARE_MGROUP(MVTYSH) #define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD #define VTYSH_NS VTYSH_ZEBRA #define VTYSH_VRF VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_STATICD +#define VTYSH_KEYS VTYSH_RIPD|VTYSH_EIGRPD enum vtysh_write_integrated { WRITE_INTEGRATED_UNSPECIFIED, diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c index 7a55da462d..541eafcf7f 100644 --- a/vtysh/vtysh_config.c +++ b/vtysh/vtysh_config.c @@ -132,16 +132,83 @@ static void config_add_line_uniq(struct list *config, const char *line) } /* - * I want to explicitly move this command to the end of the line + * Add a line that should only be shown once, and always show at the end of the + * config block. + * + * If the line already exists, it will be moved to the end of the block. If it + * does not exist, it will be added at the end of the block. + * + * Note that this only makes sense when there is just one such line that should + * show up at the very end of a config block. Furthermore, if the same block + * can show up from multiple daemons, all of them must make sure to print the + * line at the end of their config, otherwise the line will show at the end of + * the config for the last daemon that printed it. + * + * Here is a motivating example with the 'exit-vrf' command. Suppose we receive + * a config from Zebra like so: + * + * vrf BLUE + * ip route A + * ip route B + * exit-vrf + * + * Then suppose we later receive this config from PIM: + * + * vrf BLUE + * ip msdp mesh-group MyGroup member 1.2.3.4 + * exit-vrf + * + * Then we will combine them into one config block like so: + * + * vrf BLUE + * ip route A + * ip route B + * ip msdp mesh-group MyGroup member 1.2.3.4 + * exit-vrf + * + * Because PIM also sent us an 'exit-vrf', we noticed that we already had one + * under the 'vrf BLUE' config block and so we moved it to the end of the + * config block again. If PIM had neglected to send us 'exit-vrf', the result + * would be this: + * + * vrf BLUE + * ip route A + * ip route B + * exit-vrf + * ip msdp mesh-group MyGroup member 1.2.3.4 + * + * Therefore, daemons that share config blocks must take care to consistently + * print the same block terminators. + * + * Ideally this would be solved by adding a string to struct config that is + * always printed at the end when dumping a config. However, this would only + * work when the user is using integrated config. In the non-integrated config + * case, daemons are responsible for writing their own config files, and so the + * must be able to print these blocks correctly independently of vtysh, which + * means they are the ones that need to handle printing the block terminators + * and VTYSH needs to be smart enough to combine them properly. + * + * --- + * + * config + * The config to add the line to + * + * line + * The line to add to the end of the config */ -static void config_add_line_end(struct list *config, const char *line) +static void config_add_line_uniq_end(struct list *config, const char *line) { struct listnode *node; - void *item = XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line); + char *pnt; - listnode_add(config, item); - node = listnode_lookup(config, item); - if (node) + for (ALL_LIST_ELEMENTS_RO(config, node, pnt)) { + if (strcmp(pnt, line) == 0) + break; + } + + if (!node) + config_add_line(config, line); + else listnode_move_to_tail(config, node); } @@ -158,8 +225,6 @@ void vtysh_config_parse_line(void *arg, const char *line) if (c == '\0') return; - /* printf ("[%s]\n", line); */ - switch (c) { /* Suppress exclamation points ! and commented lines. The !s are * generated @@ -178,10 +243,10 @@ void vtysh_config_parse_line(void *arg, const char *line) } else if (strncmp(line, " ip multicast boundary", strlen(" ip multicast boundary")) == 0) { - config_add_line_end(config->line, line); + config_add_line_uniq_end(config->line, line); } else if (strncmp(line, " ip igmp query-interval", strlen(" ip igmp query-interval")) == 0) { - config_add_line_end(config->line, line); + config_add_line_uniq_end(config->line, line); } else if (config->index == LINK_PARAMS_NODE && strncmp(line, " exit-link-params", strlen(" exit")) @@ -192,8 +257,7 @@ void vtysh_config_parse_line(void *arg, const char *line) && strncmp(line, " exit-vrf", strlen(" exit-vrf")) == 0) { - config_add_line(config->line, line); - config->index = CONFIG_NODE; + config_add_line_uniq_end(config->line, line); } else if (config->index == RMAP_NODE || config->index == INTERFACE_NODE || config->index == LOGICALROUTER_NODE @@ -271,18 +335,18 @@ void vtysh_config_parse_line(void *arg, const char *line) strlen("ipv6 prefix-list")) == 0) config = config_get(PREFIX_IPV6_NODE, line); - else if (strncmp(line, "ip as-path access-list", - strlen("ip as-path access-list")) + else if (strncmp(line, "bgp as-path access-list", + strlen("bgp as-path access-list")) == 0) config = config_get(AS_LIST_NODE, line); - else if (strncmp(line, "ip community-list", - strlen("ip community-list")) + else if (strncmp(line, "bgp community-list", + strlen("bgp community-list")) == 0 - || strncmp(line, "ip extcommunity-list", - strlen("ip extcommunity-list")) + || strncmp(line, "bgp extcommunity-list", + strlen("bgp extcommunity-list")) == 0 - || strncmp(line, "ip large-community-list", - strlen("ip large-community-list")) + || strncmp(line, "bgp large-community-list", + strlen("bgp large-community-list")) == 0) config = config_get(COMMUNITY_LIST_NODE, line); else if (strncmp(line, "ip route", strlen("ip route")) == 0) diff --git a/zebra/debug.c b/zebra/debug.c index 19582bb090..0eb06d7f25 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -275,6 +275,7 @@ DEFUN (debug_zebra_dplane, "Detailed debug information\n") { int idx = 0; + SET_FLAG(zebra_debug_dplane, ZEBRA_DEBUG_DPLANE); if (argv_find(argv, argc, "detailed", &idx)) diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c index 3f918c361a..44afd266bc 100644 --- a/zebra/if_sysctl.c +++ b/zebra/if_sysctl.c @@ -61,7 +61,7 @@ void ifstat_update_sysctl(void) /* We free this memory at the end of this function. */ ref = buf = XMALLOC(MTYPE_TMP, bufsiz); - /* Fetch interface informations into allocated buffer. */ + /* Fetch interface information into allocated buffer. */ if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { flog_warn(EC_ZEBRA_SYSCTL_FAILED, "sysctl error by %s", safe_strerror(errno)); @@ -113,7 +113,7 @@ void interface_list(struct zebra_ns *zns) /* We free this memory at the end of this function. */ ref = buf = XMALLOC(MTYPE_TMP, bufsiz); - /* Fetch interface informations into allocated buffer. */ + /* Fetch interface information into allocated buffer. */ if (sysctl(mib, MIBSIZ, buf, &bufsiz, NULL, 0) < 0) { flog_err_sys(EC_ZEBRA_IFLIST_FAILED, "Could not enumerate interfaces: %s", diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 2b5bf04ade..bebccd7168 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -97,7 +97,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp) if (len != iplen) { flog_err(EC_ZEBRA_IRDP_LEN_MISMATCH, - "IRDP: RX length doesnt match IP length"); + "IRDP: RX length doesn't match IP length"); return; } @@ -108,7 +108,7 @@ static void parse_irdp_packet(char *p, int len, struct interface *ifp) return; } - /* XXX: RAW doesnt receive link-layer, surely? ??? */ + /* XXX: RAW doesn't receive link-layer, surely? ??? */ /* Check so we don't checksum packets longer than oure RX_BUF - (ethlen + len of IP-header) 14+20 */ diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c index e6610f21be..0772c59b92 100644 --- a/zebra/kernel_netlink.c +++ b/zebra/kernel_netlink.c @@ -136,6 +136,7 @@ extern uint32_t nl_rcvbufsize; extern struct zebra_privs_t zserv_privs; + int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns_id, int startup) { /* @@ -313,11 +314,17 @@ bool netlink_read; */ void netlink_read_init(const char *fname) { + struct zebra_dplane_info dp_info; + snprintf(netlink_fuzz_file, MAXPATHLEN, "%s", fname); /* Creating this fake socket for testing purposes */ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); - netlink_parse_info(netlink_information_fetch, &zns->netlink, zns, 1, 0); + /* Capture key info from zns struct */ + zebra_dplane_info_from_zns(&dp_info, zns, false); + + netlink_parse_info(netlink_information_fetch, &zns->netlink, + &dp_info, 1, 0); } /** @@ -678,7 +685,8 @@ static void netlink_parse_extended_ack(struct nlmsghdr *h) * the filter. */ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), - struct nlsock *nl, struct zebra_dplane_info *zns, + const struct nlsock *nl, + const struct zebra_dplane_info *zns, int count, int startup) { int status; @@ -919,28 +927,27 @@ int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), } /* - * netlink_talk + * netlink_talk_info * * sendmsg() to netlink socket then recvmsg(). * Calls netlink_parse_info to parse returned data * * filter -> The filter to read final results from kernel * nlmsghdr -> The data to send to the kernel - * nl -> The netlink socket information - * zns -> The zebra namespace information + * dp_info -> The dataplane and netlink socket information * startup -> Are we reading in under startup conditions * This is passed through eventually to filter. */ -int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), - struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, - int startup) +int netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), + struct nlmsghdr *n, + const struct zebra_dplane_info *dp_info, int startup) { int status = 0; struct sockaddr_nl snl; struct iovec iov; struct msghdr msg; int save_errno = 0; - struct zebra_dplane_info dp_info; + const struct nlsock *nl; memset(&snl, 0, sizeof snl); memset(&iov, 0, sizeof iov); @@ -955,7 +962,8 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), snl.nl_family = AF_NETLINK; - n->nlmsg_seq = ++nl->seq; + nl = &(dp_info->nls); + n->nlmsg_seq = nl->seq; n->nlmsg_pid = nl->snl.nl_pid; if (IS_ZEBRA_DEBUG_KERNEL) @@ -982,13 +990,32 @@ int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), return -1; } - /* * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ + return netlink_parse_info(filter, nl, dp_info, 0, startup); +} + +/* + * Synchronous version of netlink_talk_info. Converts args to suit the + * common version, which is suitable for both sync and async use. + */ +int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), + struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, + int startup) +{ + struct zebra_dplane_info dp_info; + + /* Increment sequence number before capturing snapshot of ns socket + * info. + */ + nl->seq++; + + /* Capture info in intermediate info struct */ zebra_dplane_info_from_zns(&dp_info, zns, (nl == &(zns->netlink_cmd))); - return netlink_parse_info(filter, nl, &dp_info, 0, startup); + + return netlink_talk_info(filter, n, &dp_info, startup); } /* Issue request message to kernel via netlink socket. GET messages diff --git a/zebra/kernel_netlink.h b/zebra/kernel_netlink.h index d78958d72e..9918729eb6 100644 --- a/zebra/kernel_netlink.h +++ b/zebra/kernel_netlink.h @@ -52,12 +52,18 @@ extern bool netlink_read; extern void netlink_read_init(const char *fname); #endif /* HANDLE_NETLINK_FUZZING */ extern int netlink_parse_info(int (*filter)(struct nlmsghdr *, ns_id_t, int), - struct nlsock *nl, struct zebra_dplane_info *zns, + const struct nlsock *nl, + const struct zebra_dplane_info *dp_info, int count, int startup); extern int netlink_talk_filter(struct nlmsghdr *h, ns_id_t ns, int startup); extern int netlink_talk(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), struct nlmsghdr *n, struct nlsock *nl, struct zebra_ns *zns, int startup); +/* Version with 'info' struct only */ +int netlink_talk_info(int (*filter)(struct nlmsghdr *, ns_id_t, int startup), + struct nlmsghdr *n, + const struct zebra_dplane_info *dp_info, int startup); + extern int netlink_request(struct nlsock *nl, struct nlmsghdr *n); #endif /* HAVE_NETLINK */ diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index 8df5a37640..bbae6061da 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -48,6 +48,7 @@ #include "zebra/kernel_socket.h" #include "zebra/rib.h" #include "zebra/zebra_errors.h" +#include "zebra/zebra_ptm.h" extern struct zebra_privs_t zserv_privs; @@ -469,7 +470,7 @@ int ifm_read(struct if_msghdr *ifm) if (ifnlen && (strncmp(ifp->name, ifname, IFNAMSIZ) != 0)) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( - "%s: ifp name %s doesnt match sdl name %s", + "%s: ifp name %s doesn't match sdl name %s", __func__, ifp->name, ifname); ifp = NULL; } diff --git a/zebra/main.c b/zebra/main.c index 148bcab7e4..ce18cf849c 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -39,6 +39,7 @@ #include "routemap.h" #include "frr_pthread.h" +#include "zebra/zebra_router.h" #include "zebra/zebra_errors.h" #include "zebra/rib.h" #include "zebra/zserv.h" @@ -142,11 +143,19 @@ static void sigint(void) struct zebra_vrf *zvrf; struct listnode *ln, *nn; struct zserv *client; + static bool sigint_done; + + if (sigint_done) + return; + + sigint_done = true; zlog_notice("Terminating on signal"); frr_early_fini(); + zebra_dplane_pre_finish(); + for (ALL_LIST_ELEMENTS(zebrad.client_list, ln, nn, client)) zserv_close_client(client); @@ -171,9 +180,30 @@ static void sigint(void) route_map_finish(); list_delete(&zebrad.client_list); + + /* Indicate that all new dplane work has been enqueued. When that + * work is complete, the dataplane will enqueue an event + * with the 'finalize' function. + */ + zebra_dplane_finish(); +} + +/* + * Final shutdown step for the zebra main thread. This is run after all + * async update processing has completed. + */ +int zebra_finalize(struct thread *dummy) +{ + zlog_info("Zebra final shutdown"); + + /* Stop dplane thread and finish any cleanup */ + zebra_dplane_shutdown(); + work_queue_free_and_null(&zebrad.ribq); meta_queue_free(zebrad.mq); + zebra_router_terminate(); + frr_fini(); exit(0); } @@ -354,6 +384,7 @@ int main(int argc, char **argv) zebrad.master = frr_init(); /* Zebra related initialize. */ + zebra_router_init(); zserv_init(); rib_init(); zebra_if_init(); @@ -418,7 +449,7 @@ int main(int argc, char **argv) /* RNH init */ zebra_rnh_init(); - + /* Error init */ zebra_error_init(); diff --git a/zebra/redistribute.h b/zebra/redistribute.h index f67480da9c..f0dc79574c 100644 --- a/zebra/redistribute.h +++ b/zebra/redistribute.h @@ -38,10 +38,11 @@ extern void zebra_redistribute_default_delete(ZAPI_HANDLER_ARGS); extern void redistribute_update(const struct prefix *p, const struct prefix *src_p, - struct route_entry *, struct route_entry *); + struct route_entry *re, + struct route_entry *prev_re); extern void redistribute_delete(const struct prefix *p, const struct prefix *src_p, - struct route_entry *); + struct route_entry *re); extern void zebra_interface_up_update(struct interface *); extern void zebra_interface_down_update(struct interface *); diff --git a/zebra/rib.h b/zebra/rib.h index f3aead32d8..97eae79f03 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -91,6 +91,9 @@ struct route_entry { /* Nexthop information. */ uint8_t nexthop_num; uint8_t nexthop_active_num; + + /* Sequence value incremented for each dataplane operation */ + uint32_t dplane_sequence; }; /* meta-queue structure: diff --git a/zebra/rt.h b/zebra/rt.h index dbea298584..70ac6f635c 100644 --- a/zebra/rt.h +++ b/zebra/rt.h @@ -32,31 +32,11 @@ #include "zebra/zebra_dplane.h" /* - * Install/delete the specified prefix p from the kernel - * - * old = NULL, new = pointer - Install new - * old = pointer, new = pointer - Route replace Old w/ New - * old = pointer, new = NULL, - Route Delete - * - * Please note not all kernels support route replace - * semantics so we will end up with a delete than - * a re-add. + * Update or delete a prefix from the kernel, + * using info from a dataplane context. */ -extern enum zebra_dplane_result kernel_route_rib(struct route_node *rn, - const struct prefix *p, - const struct prefix *src_p, - struct route_entry *old, - struct route_entry *new); - -/* - * So route install/failure may not be immediately known - * so let's separate it out and allow the result to - * be passed back up. - */ -extern void kernel_route_rib_pass_fail(struct route_node *rn, - const struct prefix *p, - struct route_entry *re, - enum zebra_dplane_status res); +extern enum zebra_dplane_result kernel_route_update( + struct zebra_dplane_ctx *ctx); extern int kernel_address_add_ipv4(struct interface *, struct connected *); extern int kernel_address_delete_ipv4(struct interface *, struct connected *); diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 795ee2703a..a65d477f03 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1443,21 +1443,21 @@ static int netlink_neigh_update(int cmd, int ifindex, uint32_t addr, char *lla, 0); } -/* Routing table change via netlink interface. */ -/* Update flag indicates whether this is a "replace" or not. */ -static int netlink_route_multipath(int cmd, const struct prefix *p, - const struct prefix *src_p, - struct route_entry *re, - int update) +/* + * Routing table change via netlink interface, using a dataplane context object + */ +static int netlink_route_multipath(int cmd, struct zebra_dplane_ctx *ctx) { int bytelen; struct sockaddr_nl snl; struct nexthop *nexthop = NULL; unsigned int nexthop_num; - int family = PREFIX_FAMILY(p); + int family; const char *routedesc; int setsrc = 0; union g_addr src; + const struct prefix *p, *src_p; + uint32_t table_id; struct { struct nlmsghdr n; @@ -1465,27 +1465,37 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, char buf[NL_PKT_BUF_SIZE]; } req; - struct zebra_ns *zns; - struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + p = dplane_ctx_get_dest(ctx); + src_p = dplane_ctx_get_src(ctx); - zns = zvrf->zns; - memset(&req, 0, sizeof req - NL_PKT_BUF_SIZE); + family = PREFIX_FAMILY(p); + + memset(&req, 0, sizeof(req) - NL_PKT_BUF_SIZE); bytelen = (family == AF_INET ? 4 : 16); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); req.n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST; - if ((cmd == RTM_NEWROUTE) && update) - req.n.nlmsg_flags |= NLM_F_REPLACE; + + if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) { + if ((p->family == AF_INET) || v6_rr_semantics) + req.n.nlmsg_flags |= NLM_F_REPLACE; + } + req.n.nlmsg_type = cmd; - req.n.nlmsg_pid = zns->netlink_cmd.snl.nl_pid; + + req.n.nlmsg_pid = dplane_ctx_get_ns(ctx)->nls.snl.nl_pid; req.r.rtm_family = family; req.r.rtm_dst_len = p->prefixlen; req.r.rtm_src_len = src_p ? src_p->prefixlen : 0; - req.r.rtm_protocol = zebra2proto(re->type); req.r.rtm_scope = RT_SCOPE_UNIVERSE; + if (cmd == RTM_DELROUTE) + req.r.rtm_protocol = zebra2proto(dplane_ctx_get_old_type(ctx)); + else + req.r.rtm_protocol = zebra2proto(dplane_ctx_get_type(ctx)); + /* * blackhole routes are not RTN_UNICAST, they are * RTN_ BLACKHOLE|UNREACHABLE|PROHIBIT @@ -1497,9 +1507,9 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, if (cmd != RTM_DELROUTE) req.r.rtm_type = RTN_UNICAST; - addattr_l(&req.n, sizeof req, RTA_DST, &p->u.prefix, bytelen); + addattr_l(&req.n, sizeof(req), RTA_DST, &p->u.prefix, bytelen); if (src_p) - addattr_l(&req.n, sizeof req, RTA_SRC, &src_p->u.prefix, + addattr_l(&req.n, sizeof(req), RTA_SRC, &src_p->u.prefix, bytelen); /* Metric. */ @@ -1509,20 +1519,31 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, * path(s) * by the routing protocol and for communicating with protocol peers. */ - addattr32(&req.n, sizeof req, RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + addattr32(&req.n, sizeof(req), RTA_PRIORITY, NL_DEFAULT_ROUTE_METRIC); + #if defined(SUPPORT_REALMS) - if (re->tag > 0 && re->tag <= 255) - addattr32(&req.n, sizeof req, RTA_FLOW, re->tag); + { + route_tag_t tag; + + if (cmd == RTM_DELROUTE) + tag = dplane_ctx_get_old_tag(ctx); + else + tag = dplane_ctx_get_tag(ctx); + + if (tag > 0 && tag <= 255) + addattr32(&req.n, sizeof(req), RTA_FLOW, tag); + } #endif /* Table corresponding to this route. */ - if (re->table < 256) - req.r.rtm_table = re->table; + table_id = dplane_ctx_get_table(ctx); + if (table_id < 256) + req.r.rtm_table = table_id; else { req.r.rtm_table = RT_TABLE_UNSPEC; - addattr32(&req.n, sizeof req, RTA_TABLE, re->table); + addattr32(&req.n, sizeof(req), RTA_TABLE, table_id); } - _netlink_route_debug(cmd, p, family, zvrf_id(zvrf), re->table); + _netlink_route_debug(cmd, p, family, dplane_ctx_get_vrf(ctx), table_id); /* * If we are not updating the route and we have received @@ -1530,33 +1551,34 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, * prefix information to tell the kernel to schwack * it. */ - if (!update && cmd == RTM_DELROUTE) + if (cmd == RTM_DELROUTE) goto skip; - if (re->mtu || re->nexthop_mtu) { + if (dplane_ctx_get_mtu(ctx) || dplane_ctx_get_nh_mtu(ctx)) { char buf[NL_PKT_BUF_SIZE]; struct rtattr *rta = (void *)buf; - uint32_t mtu = re->mtu; - if (!mtu || (re->nexthop_mtu && re->nexthop_mtu < mtu)) - mtu = re->nexthop_mtu; + uint32_t mtu = dplane_ctx_get_mtu(ctx); + uint32_t nexthop_mtu = dplane_ctx_get_nh_mtu(ctx); + + if (!mtu || (nexthop_mtu && nexthop_mtu < mtu)) + mtu = nexthop_mtu; rta->rta_type = RTA_METRICS; rta->rta_len = RTA_LENGTH(0); - rta_addattr_l(rta, NL_PKT_BUF_SIZE, RTAX_MTU, &mtu, sizeof mtu); + rta_addattr_l(rta, NL_PKT_BUF_SIZE, + RTAX_MTU, &mtu, sizeof(mtu)); addattr_l(&req.n, NL_PKT_BUF_SIZE, RTA_METRICS, RTA_DATA(rta), RTA_PAYLOAD(rta)); } /* Count overall nexthops so we can decide whether to use singlepath - * or multipath case. */ + * or multipath case. + */ nexthop_num = 0; - for (ALL_NEXTHOPS(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; if (cmd == RTM_NEWROUTE && !NEXTHOP_IS_ACTIVE(nexthop->flags)) continue; - if (cmd == RTM_DELROUTE - && !CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB)) - continue; nexthop_num++; } @@ -1564,7 +1586,7 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, /* Singlepath case. */ if (nexthop_num == 1 || multipath_num == 1) { nexthop_num = 0; - for (ALL_NEXTHOPS(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { /* * So we want to cover 2 types of blackhole * routes here: @@ -1588,70 +1610,61 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, } if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) { - if (!setsrc) { - if (family == AF_INET) { - if (nexthop->rmap_src.ipv4 - .s_addr - != 0) { - src.ipv4 = - nexthop->rmap_src - .ipv4; - setsrc = 1; - } else if (nexthop->src.ipv4 - .s_addr - != 0) { - src.ipv4 = - nexthop->src - .ipv4; - setsrc = 1; - } - } else if (family == AF_INET6) { - if (!IN6_IS_ADDR_UNSPECIFIED( - &nexthop->rmap_src - .ipv6)) { - src.ipv6 = - nexthop->rmap_src - .ipv6; - setsrc = 1; - } else if ( - !IN6_IS_ADDR_UNSPECIFIED( - &nexthop->src - .ipv6)) { - src.ipv6 = - nexthop->src - .ipv6; - setsrc = 1; - } + + if (setsrc) + continue; + + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4.s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src.ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4.s_addr + != 0) { + src.ipv4 = + nexthop->src.ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src.ipv6)) { + src.ipv6 = + nexthop->rmap_src.ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src.ipv6)) { + src.ipv6 = + nexthop->src.ipv6; + setsrc = 1; } } continue; } if ((cmd == RTM_NEWROUTE - && NEXTHOP_IS_ACTIVE(nexthop->flags)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB))) { + && NEXTHOP_IS_ACTIVE(nexthop->flags))) { routedesc = nexthop->rparent ? "recursive, single-path" : "single-path"; _netlink_route_build_singlepath( routedesc, bytelen, nexthop, &req.n, - &req.r, sizeof req, cmd); + &req.r, sizeof(req), cmd); nexthop_num++; break; } } if (setsrc && (cmd == RTM_NEWROUTE)) { if (family == AF_INET) - addattr_l(&req.n, sizeof req, RTA_PREFSRC, + addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &src.ipv4, bytelen); else if (family == AF_INET6) - addattr_l(&req.n, sizeof req, RTA_PREFSRC, + addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &src.ipv6, bytelen); } - } else { + } else { /* Multipath case */ char buf[NL_PKT_BUF_SIZE]; struct rtattr *rta = (void *)buf; struct rtnexthop *rtnh; @@ -1662,57 +1675,46 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, rtnh = RTA_DATA(rta); nexthop_num = 0; - for (ALL_NEXTHOPS(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { if (nexthop_num >= multipath_num) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) { /* This only works for IPv4 now */ - if (!setsrc) { - if (family == AF_INET) { - if (nexthop->rmap_src.ipv4 - .s_addr - != 0) { - src.ipv4 = - nexthop->rmap_src - .ipv4; - setsrc = 1; - } else if (nexthop->src.ipv4 - .s_addr - != 0) { - src.ipv4 = - nexthop->src - .ipv4; - setsrc = 1; - } - } else if (family == AF_INET6) { - if (!IN6_IS_ADDR_UNSPECIFIED( - &nexthop->rmap_src - .ipv6)) { - src.ipv6 = - nexthop->rmap_src - .ipv6; - setsrc = 1; - } else if ( - !IN6_IS_ADDR_UNSPECIFIED( - &nexthop->src - .ipv6)) { - src.ipv6 = - nexthop->src - .ipv6; - setsrc = 1; - } + if (setsrc) + continue; + + if (family == AF_INET) { + if (nexthop->rmap_src.ipv4.s_addr + != 0) { + src.ipv4 = + nexthop->rmap_src.ipv4; + setsrc = 1; + } else if (nexthop->src.ipv4.s_addr + != 0) { + src.ipv4 = + nexthop->src.ipv4; + setsrc = 1; + } + } else if (family == AF_INET6) { + if (!IN6_IS_ADDR_UNSPECIFIED( + &nexthop->rmap_src.ipv6)) { + src.ipv6 = + nexthop->rmap_src.ipv6; + setsrc = 1; + } else if ( + !IN6_IS_ADDR_UNSPECIFIED( + &nexthop->src.ipv6)) { + src.ipv6 = + nexthop->src.ipv6; + setsrc = 1; } } - continue; } if ((cmd == RTM_NEWROUTE - && NEXTHOP_IS_ACTIVE(nexthop->flags)) - || (cmd == RTM_DELROUTE - && CHECK_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB))) { + && NEXTHOP_IS_ACTIVE(nexthop->flags))) { routedesc = nexthop->rparent ? "recursive, multipath" : "multipath"; @@ -1735,10 +1737,10 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, } if (setsrc && (cmd == RTM_NEWROUTE)) { if (family == AF_INET) - addattr_l(&req.n, sizeof req, RTA_PREFSRC, + addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &src.ipv4, bytelen); else if (family == AF_INET6) - addattr_l(&req.n, sizeof req, RTA_PREFSRC, + addattr_l(&req.n, sizeof(req), RTA_PREFSRC, &src.ipv6, bytelen); if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("Setting source"); @@ -1760,12 +1762,12 @@ static int netlink_route_multipath(int cmd, const struct prefix *p, skip: /* Destination netlink address. */ - memset(&snl, 0, sizeof snl); + memset(&snl, 0, sizeof(snl)); snl.nl_family = AF_NETLINK; /* Talk to netlink socket. */ - return netlink_talk(netlink_talk_filter, &req.n, &zns->netlink_cmd, zns, - 0); + return netlink_talk_info(netlink_talk_filter, &req.n, + dplane_ctx_get_ns(ctx), 0); } int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) @@ -1821,25 +1823,30 @@ int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *in) return suc; } -enum zebra_dplane_result kernel_route_rib(struct route_node *rn, - const struct prefix *p, - const struct prefix *src_p, - struct route_entry *old, - struct route_entry *new) +/* + * Update or delete a prefix from the kernel, + * using info from a dataplane context. + */ +enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) { - int ret = 0; + int cmd, ret; + const struct prefix *p = dplane_ctx_get_dest(ctx); + struct nexthop *nexthop; - assert(old || new); + if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) { + cmd = RTM_DELROUTE; + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) { + cmd = RTM_NEWROUTE; + } else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) { - if (new) { - if (p->family == AF_INET || v6_rr_semantics) - ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p, - new, (old) ? 1 : 0); - else { + if (p->family == AF_INET || v6_rr_semantics) { + /* Single 'replace' operation */ + cmd = RTM_NEWROUTE; + } else { /* * So v6 route replace semantics are not in * the kernel at this point as I understand it. - * So let's do a delete than an add. + * so let's do a delete then an add. * In the future once v6 route replace semantics * are in we can figure out what to do here to * allow working with old and new kernels. @@ -1848,27 +1855,37 @@ enum zebra_dplane_result kernel_route_rib(struct route_node *rn, * of the route delete. If that happens yeah we're * screwed. */ - if (old) - netlink_route_multipath(RTM_DELROUTE, p, src_p, - old, 0); - ret = netlink_route_multipath(RTM_NEWROUTE, p, src_p, - new, 0); + (void)netlink_route_multipath(RTM_DELROUTE, ctx); + cmd = RTM_NEWROUTE; } - kernel_route_rib_pass_fail(rn, p, new, - (!ret) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - return ZEBRA_DPLANE_REQUEST_SUCCESS; + + } else { + return ZEBRA_DPLANE_REQUEST_FAILURE; } - if (old) { - ret = netlink_route_multipath(RTM_DELROUTE, p, src_p, old, 0); + ret = netlink_route_multipath(cmd, ctx); + if ((cmd == RTM_NEWROUTE) && (ret == 0)) { + /* Update installed nexthops to signal which have been + * installed. + */ + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) { + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; - kernel_route_rib_pass_fail(rn, p, old, - (!ret) ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) { + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + + /* If we're only allowed a single nh, don't + * continue. + */ + if (multipath_num == 1) + break; + } + } } - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return (ret == 0 ? + ZEBRA_DPLANE_REQUEST_SUCCESS : ZEBRA_DPLANE_REQUEST_FAILURE); } int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, diff --git a/zebra/rt_socket.c b/zebra/rt_socket.c index e8d0b71605..99a7ca5d55 100644 --- a/zebra/rt_socket.c +++ b/zebra/rt_socket.c @@ -91,7 +91,7 @@ static int kernel_rtm_add_labels(struct mpls_label_stack *nh_label, /* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, - struct route_entry *re) + const struct nexthop_group *ng, uint32_t metric) { struct sockaddr_in *mask = NULL; @@ -126,7 +126,7 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Make gateway. */ - for (ALL_NEXTHOPS(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(ng, nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; @@ -139,8 +139,7 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, * other than ADD and DELETE? */ if ((cmd == RTM_ADD && NEXTHOP_IS_ACTIVE(nexthop->flags)) - || (cmd == RTM_DELETE - && CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))) { + || (cmd == RTM_DELETE)) { if (nexthop->type == NEXTHOP_TYPE_IPV4 || nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX) { sin_gate.sin_addr = nexthop->gate.ipv4; @@ -181,14 +180,13 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, - smplsp, ifindex, bh_type, re->metric); + smplsp, ifindex, bh_type, metric); - if (IS_ZEBRA_DEBUG_RIB) { + if (IS_ZEBRA_DEBUG_KERNEL) { if (!gate) { zlog_debug( - "%s: %s: attention! gate not found for re %p", - __func__, prefix_buf, re); - route_entry_dump(p, NULL, re); + "%s: %s: attention! gate not found for re", + __func__, prefix_buf); } else inet_ntop(AF_INET, &sin_gate.sin_addr, gate_buf, INET_ADDRSTRLEN); @@ -199,10 +197,15 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, * did its work. */ case ZEBRA_ERR_NOERROR: nexthop_num++; - if (IS_ZEBRA_DEBUG_RIB) + if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug( "%s: %s: successfully did NH %s", __func__, prefix_buf, gate_buf); + + if (cmd == RTM_ADD) + SET_FLAG(nexthop->flags, + NEXTHOP_FLAG_FIB); + break; /* The only valid case for this error is kernel's @@ -218,14 +221,8 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, "%s: rtm_write() returned %d for command %d", __func__, error, cmd); continue; - break; - /* Given that our NEXTHOP_FLAG_FIB matches real kernel - * FIB, it isn't - * normal to get any other messages in ANY case. - */ - case ZEBRA_ERR_RTNOEXIST: - case ZEBRA_ERR_RTUNREACH: + /* Note any unexpected status returns */ default: flog_err( EC_LIB_SYSTEM_CALL, @@ -238,16 +235,20 @@ static int kernel_rtm_ipv4(int cmd, const struct prefix *p, break; } } /* if (cmd and flags make sense) */ - else if (IS_ZEBRA_DEBUG_RIB) + else if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("%s: odd command %s for flags %d", __func__, lookup_msg(rtm_type_str, cmd, NULL), nexthop->flags); } /* for (ALL_NEXTHOPS(...))*/ /* If there was no useful nexthop, then complain. */ - if (nexthop_num == 0 && IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("%s: No useful nexthops were found in RIB entry %p", - __func__, re); + if (nexthop_num == 0) { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug("%s: No useful nexthops were found in RIB prefix %s", + __func__, prefix2str(p, prefix_buf, + sizeof(prefix_buf))); + return 1; + } return 0; /*XXX*/ } @@ -278,7 +279,7 @@ static int sin6_masklen(struct in6_addr mask) /* Interface between zebra message and rtm message. */ static int kernel_rtm_ipv6(int cmd, const struct prefix *p, - struct route_entry *re) + const struct nexthop_group *ng, uint32_t metric) { struct sockaddr_in6 *mask; struct sockaddr_in6 sin_dest, sin_mask, sin_gate; @@ -309,7 +310,7 @@ static int kernel_rtm_ipv6(int cmd, const struct prefix *p, #endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */ /* Make gateway. */ - for (ALL_NEXTHOPS(re->ng, nexthop)) { + for (ALL_NEXTHOPS_PTR(ng, nexthop)) { if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) continue; @@ -364,8 +365,11 @@ static int kernel_rtm_ipv6(int cmd, const struct prefix *p, error = rtm_write(cmd, (union sockunion *)&sin_dest, (union sockunion *)mask, gate ? (union sockunion *)&sin_gate : NULL, - smplsp, ifindex, bh_type, re->metric); - (void)error; + smplsp, ifindex, bh_type, metric); + + /* Update installed nexthop info on success */ + if ((cmd == RTM_ADD) && (error == ZEBRA_ERR_NOERROR)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); nexthop_num++; } @@ -374,60 +378,70 @@ static int kernel_rtm_ipv6(int cmd, const struct prefix *p, if (nexthop_num == 0) { if (IS_ZEBRA_DEBUG_KERNEL) zlog_debug("kernel_rtm_ipv6(): No useful nexthop."); - return 0; + return 1; } return 0; /*XXX*/ } -static int kernel_rtm(int cmd, const struct prefix *p, struct route_entry *re) +static int kernel_rtm(int cmd, const struct prefix *p, + const struct nexthop_group *ng, uint32_t metric) { switch (PREFIX_FAMILY(p)) { case AF_INET: - return kernel_rtm_ipv4(cmd, p, re); + return kernel_rtm_ipv4(cmd, p, ng, metric); case AF_INET6: - return kernel_rtm_ipv6(cmd, p, re); + return kernel_rtm_ipv6(cmd, p, ng, metric); } return 0; } -enum zebra_dplane_result kernel_route_rib(struct route_node *rn, - const struct prefix *p, - const struct prefix *src_p, - struct route_entry *old, - struct route_entry *new) +/* + * Update or delete a prefix from the kernel, + * using info from a dataplane context struct. + */ +enum zebra_dplane_result kernel_route_update(struct zebra_dplane_ctx *ctx) { - int route = 0; + enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS; - if (src_p && src_p->prefixlen) { - flog_warn(EC_ZEBRA_UNSUPPORTED_V6_SRCDEST, - "%s: IPv6 sourcedest routes unsupported!", __func__); - return ZEBRA_DPLANE_REQUEST_FAILURE; + if (dplane_ctx_get_src(ctx) != NULL) { + zlog_err("route add: IPv6 sourcedest routes unsupported!"); + res = ZEBRA_DPLANE_REQUEST_FAILURE; + goto done; } - frr_elevate_privs(&zserv_privs) { + frr_elevate_privs(ZPRIVS_RAISE) { - if (old) - route |= kernel_rtm(RTM_DELETE, p, old); + if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_DELETE) + kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); + else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_INSTALL) + kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); + else if (dplane_ctx_get_op(ctx) == DPLANE_OP_ROUTE_UPDATE) { + /* Must do delete and add separately - + * no update available + */ + kernel_rtm(RTM_DELETE, dplane_ctx_get_dest(ctx), + dplane_ctx_get_old_ng(ctx), + dplane_ctx_get_old_metric(ctx)); - if (new) - route |= kernel_rtm(RTM_ADD, p, new); + kernel_rtm(RTM_ADD, dplane_ctx_get_dest(ctx), + dplane_ctx_get_ng(ctx), + dplane_ctx_get_metric(ctx)); + } else { + zlog_err("Invalid routing socket update op %s (%u)", + dplane_op2str(dplane_ctx_get_op(ctx)), + dplane_ctx_get_op(ctx)); + res = ZEBRA_DPLANE_REQUEST_FAILURE; + } + } /* Elevated privs */ - } +done: - if (new) { - kernel_route_rib_pass_fail( - rn, p, new, - (!route) ? ZEBRA_DPLANE_INSTALL_SUCCESS - : ZEBRA_DPLANE_INSTALL_FAILURE); - } else { - kernel_route_rib_pass_fail(rn, p, old, - (!route) - ? ZEBRA_DPLANE_DELETE_SUCCESS - : ZEBRA_DPLANE_DELETE_FAILURE); - } - - return ZEBRA_DPLANE_REQUEST_SUCCESS; + return res; } int kernel_neigh_update(int add, int ifindex, uint32_t addr, char *lla, diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 3bb75f3446..a22f6395c9 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -45,6 +45,7 @@ #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_errors.h" +#include "zebra/zebra_router.h" extern struct zebra_privs_t zserv_privs; @@ -391,8 +392,8 @@ static int rtadv_timer(struct thread *thread) struct zebra_if *zif; int period; - zns->rtadv.ra_timer = NULL; - if (zns->rtadv.adv_msec_if_count == 0) { + zrouter.rtadv.ra_timer = NULL; + if (zrouter.rtadv.adv_msec_if_count == 0) { period = 1000; /* 1 s */ rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */); } else { @@ -424,7 +425,8 @@ static int rtadv_timer(struct thread *thread) "Fast RA Rexmit on interface %s", ifp->name); - rtadv_send_packet(zns->rtadv.sock, ifp); + rtadv_send_packet(zrouter.rtadv.sock, + ifp); } else { zif->rtadv.AdvIntervalTimer -= period; if (zif->rtadv.AdvIntervalTimer <= 0) { @@ -437,7 +439,8 @@ static int rtadv_timer(struct thread *thread) zif->rtadv .MaxRtrAdvInterval; rtadv_send_packet( - zns->rtadv.sock, ifp); + zrouter.rtadv.sock, + ifp); } } } @@ -452,7 +455,7 @@ static void rtadv_process_solicit(struct interface *ifp) struct zebra_ns *zns = zvrf->zns; assert(zns); - rtadv_send_packet(zns->rtadv.sock, ifp); + rtadv_send_packet(zrouter.rtadv.sock, ifp); } /* @@ -649,7 +652,7 @@ static int rtadv_read(struct thread *thread) struct zebra_ns *zns = THREAD_ARG(thread); sock = THREAD_FD(thread); - zns->rtadv.ra_read = NULL; + zrouter.rtadv.ra_read = NULL; /* Register myself. */ rtadv_event(zns, RTADV_READ, sock); @@ -808,18 +811,18 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, if (zif->rtadv.AdvSendAdvertisements) { zif->rtadv.AdvSendAdvertisements = 0; zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count--; + zrouter.rtadv.adv_if_count--; - if_leave_all_router(zns->rtadv.sock, ifp); + if_leave_all_router(zrouter.rtadv.sock, ifp); - if (zns->rtadv.adv_if_count == 0) + if (zrouter.rtadv.adv_if_count == 0) rtadv_event(zns, RTADV_STOP, 0); } } else { if (!zif->rtadv.AdvSendAdvertisements) { zif->rtadv.AdvSendAdvertisements = 1; zif->rtadv.AdvIntervalTimer = 0; - zns->rtadv.adv_if_count++; + zrouter.rtadv.adv_if_count++; if (zif->rtadv.MaxRtrAdvInterval >= 1000) { /* Enable Fast RA only when RA interval is in @@ -829,10 +832,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, RTADV_NUM_FAST_REXMITS; } - if_join_all_router(zns->rtadv.sock, ifp); + if_join_all_router(zrouter.rtadv.sock, ifp); - if (zns->rtadv.adv_if_count == 1) - rtadv_event(zns, RTADV_START, zns->rtadv.sock); + if (zrouter.rtadv.adv_if_count == 1) + rtadv_event(zns, RTADV_START, + zrouter.rtadv.sock); } } } @@ -972,10 +976,7 @@ DEFUN (ipv6_nd_ra_interval_msec, VTY_DECLVAR_CONTEXT(interface, ifp); unsigned interval; struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); - struct zebra_ns *zns; - zns = zvrf->zns; interval = strtoul(argv[idx_number]->arg, NULL, 10); if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) { @@ -985,10 +986,10 @@ DEFUN (ipv6_nd_ra_interval_msec, } if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; if (interval % 1000) - zns->rtadv.adv_msec_if_count++; + zrouter.rtadv.adv_msec_if_count++; SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED); zif->rtadv.MaxRtrAdvInterval = interval; @@ -1010,10 +1011,7 @@ DEFUN (ipv6_nd_ra_interval, VTY_DECLVAR_CONTEXT(interface, ifp); unsigned interval; struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); - struct zebra_ns *zns; - zns = zvrf->zns; interval = strtoul(argv[idx_number]->arg, NULL, 10); if ((zif->rtadv.AdvDefaultLifetime != -1 && interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) { @@ -1023,7 +1021,7 @@ DEFUN (ipv6_nd_ra_interval, } if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; /* convert to milliseconds */ interval = interval * 1000; @@ -1049,14 +1047,9 @@ DEFUN (no_ipv6_nd_ra_interval, { VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf; - struct zebra_ns *zns; - - zvrf = vrf_info_lookup(ifp->vrf_id); - zns = zvrf->zns; if (zif->rtadv.MaxRtrAdvInterval % 1000) - zns->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED); @@ -1701,7 +1694,7 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp) static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val) { - struct rtadv *rtadv = &zns->rtadv; + struct rtadv *rtadv = &zrouter.rtadv; switch (event) { case RTADV_START: @@ -1740,19 +1733,19 @@ static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val) void rtadv_init(struct zebra_ns *zns) { - zns->rtadv.sock = rtadv_make_socket(zns->ns_id); + zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id); } void rtadv_terminate(struct zebra_ns *zns) { rtadv_event(zns, RTADV_STOP, 0); - if (zns->rtadv.sock >= 0) { - close(zns->rtadv.sock); - zns->rtadv.sock = -1; + if (zrouter.rtadv.sock >= 0) { + close(zrouter.rtadv.sock); + zrouter.rtadv.sock = -1; } - zns->rtadv.adv_if_count = 0; - zns->rtadv.adv_msec_if_count = 0; + zrouter.rtadv.adv_if_count = 0; + zrouter.rtadv.adv_msec_if_count = 0; } void rtadv_cmd_init(void) diff --git a/zebra/subdir.am b/zebra/subdir.am index 1d76ff65ca..b8f5e0d409 100644 --- a/zebra/subdir.am +++ b/zebra/subdir.am @@ -79,6 +79,7 @@ zebra_zebra_SOURCES = \ zebra/zebra_ptm_redistribute.c \ zebra/zebra_pw.c \ zebra/zebra_rib.c \ + zebra/zebra_router.c \ zebra/zebra_rnh.c \ zebra/zebra_routemap.c \ zebra/zebra_vrf.c \ @@ -95,6 +96,10 @@ zebra_zebra_SOURCES = \ zebra/zebra_vty_clippy.c: $(CLIPPY_DEPS) zebra/zebra_vty.$(OBJEXT): zebra/zebra_vty_clippy.c + +zebra/zebra_routemap_clippy.c: $(CLIPPY_DEPS) +zebra/zebra_routemap.$(OBJEXT): zebra/zebra_routemap_clippy.c + noinst_HEADERS += \ zebra/connected.h \ zebra/debug.h \ @@ -127,6 +132,7 @@ noinst_HEADERS += \ zebra/zebra_pw.h \ zebra/zebra_rnh.h \ zebra/zebra_routemap.h \ + zebra/zebra_router.h \ zebra/zebra_vrf.h \ zebra/zebra_vxlan.h \ zebra/zebra_vxlan_private.h \ diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index b9897bea03..7ea0a4d47d 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -740,6 +740,20 @@ int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, re->table, note)); } +/* + * Route-owner notification using info from dataplane update context. + */ +int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, + enum zapi_route_notify_owner note) +{ + return (route_notify_internal(dplane_ctx_get_dest(ctx), + dplane_ctx_get_type(ctx), + dplane_ctx_get_instance(ctx), + dplane_ctx_get_vrf(ctx), + dplane_ctx_get_table(ctx), + note)); +} + void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, enum zapi_rule_notify_owner note) { @@ -1090,8 +1104,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) zebra_add_rnh_client(rnh, client, type, zvrf_id(zvrf)); /* Anything not AF_INET/INET6 has been filtered out above */ if (!exist) - zebra_evaluate_rnh(zvrf_id(zvrf), p.family, 1, type, - &p); + zebra_evaluate_rnh(zvrf, p.family, 1, type, &p); } stream_failure: @@ -2244,10 +2257,11 @@ static inline void zread_rule(ZAPI_HANDLER_ARGS) if (zpr.rule.filter.fwmark) zpr.rule.filter.filter_bm |= PBR_FILTER_FWMARK; + zpr.vrf_id = zvrf->vrf->vrf_id; if (hdr->command == ZEBRA_RULE_ADD) - zebra_pbr_add_rule(zvrf->zns, &zpr); + zebra_pbr_add_rule(&zpr); else - zebra_pbr_del_rule(zvrf->zns, &zpr); + zebra_pbr_del_rule(&zpr); } stream_failure: @@ -2273,9 +2287,9 @@ static inline void zread_ipset(ZAPI_HANDLER_ARGS) STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE); if (hdr->command == ZEBRA_IPSET_CREATE) - zebra_pbr_create_ipset(zvrf->zns, &zpi); + zebra_pbr_create_ipset(&zpi); else - zebra_pbr_destroy_ipset(zvrf->zns, &zpi); + zebra_pbr_destroy_ipset(&zpi); } stream_failure: @@ -2328,12 +2342,12 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS) zpi.filter_bm |= PBR_FILTER_PROTO; /* calculate backpointer */ - zpi.backpointer = zebra_pbr_lookup_ipset_pername( - zvrf->zns, ipset.ipset_name); + zpi.backpointer = + zebra_pbr_lookup_ipset_pername(ipset.ipset_name); if (hdr->command == ZEBRA_IPSET_ENTRY_ADD) - zebra_pbr_add_ipset_entry(zvrf->zns, &zpi); + zebra_pbr_add_ipset_entry(&zpi); else - zebra_pbr_del_ipset_entry(zvrf->zns, &zpi); + zebra_pbr_del_ipset_entry(&zpi); } stream_failure: @@ -2368,9 +2382,9 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS) zebra_pbr_iptable_update_interfacelist(s, &zpi); if (hdr->command == ZEBRA_IPTABLE_ADD) - zebra_pbr_add_iptable(zvrf->zns, &zpi); + zebra_pbr_add_iptable(&zpi); else - zebra_pbr_del_iptable(zvrf->zns, &zpi); + zebra_pbr_del_iptable(&zpi); stream_failure: return; } @@ -2440,6 +2454,7 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = { [ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry, [ZEBRA_IPTABLE_ADD] = zread_iptable, [ZEBRA_IPTABLE_DELETE] = zread_iptable, + [ZEBRA_VXLAN_FLOOD_CONTROL] = zebra_vxlan_flood_control, }; #if defined(HANDLE_ZAPI_FUZZING) diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h index 29fe59babf..11b469e144 100644 --- a/zebra/zapi_msg.h +++ b/zebra/zapi_msg.h @@ -70,6 +70,8 @@ extern int zsend_pw_update(struct zserv *client, struct zebra_pw *pw); extern int zsend_route_notify_owner(struct route_entry *re, const struct prefix *p, enum zapi_route_notify_owner note); +extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx, + enum zapi_route_notify_owner note); extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule, enum zapi_rule_notify_owner note); diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c index c0e4939860..61eba92c98 100644 --- a/zebra/zebra_dplane.c +++ b/zebra/zebra_dplane.c @@ -17,5 +17,1125 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include -#include "zebra_dplane.h" +#include "lib/libfrr.h" +#include "lib/debug.h" +#include "lib/frratomic.h" +#include "lib/frr_pthread.h" +#include "lib/memory.h" +#include "lib/queue.h" +#include "lib/zebra.h" +#include "zebra/zebra_memory.h" +#include "zebra/zserv.h" +#include "zebra/zebra_dplane.h" +#include "zebra/rt.h" +#include "zebra/debug.h" + +/* Memory type for context blocks */ +DEFINE_MTYPE(ZEBRA, DP_CTX, "Zebra DPlane Ctx") +DEFINE_MTYPE(ZEBRA, DP_PROV, "Zebra DPlane Provider") + +#ifndef AOK +# define AOK 0 +#endif + +/* Default value for max queued incoming updates */ +const uint32_t DPLANE_DEFAULT_MAX_QUEUED = 200; + + +/* Validation check macro for context blocks */ +/* #define DPLANE_DEBUG 1 */ + +#ifdef DPLANE_DEBUG + +# define DPLANE_CTX_VALID(p) \ + assert((p) != NULL) + +#else + +# define DPLANE_CTX_VALID(p) + +#endif /* DPLANE_DEBUG */ + +/* + * The context block used to exchange info about route updates across + * the boundary between the zebra main context (and pthread) and the + * dataplane layer (and pthread). + */ +struct zebra_dplane_ctx { + + /* Operation code */ + enum dplane_op_e zd_op; + + /* Status on return */ + enum zebra_dplane_result zd_status; + + /* TODO -- internal/sub-operation status? */ + enum zebra_dplane_result zd_remote_status; + enum zebra_dplane_result zd_kernel_status; + + /* Dest and (optional) source prefixes */ + struct prefix zd_dest; + struct prefix zd_src; + + bool zd_is_update; + + uint32_t zd_seq; + uint32_t zd_old_seq; + vrf_id_t zd_vrf_id; + uint32_t zd_table_id; + + int zd_type; + int zd_old_type; + + afi_t zd_afi; + safi_t zd_safi; + + route_tag_t zd_tag; + route_tag_t zd_old_tag; + uint32_t zd_metric; + uint32_t zd_old_metric; + uint16_t zd_instance; + uint16_t zd_old_instance; + + uint8_t zd_distance; + uint8_t zd_old_distance; + + uint32_t zd_mtu; + uint32_t zd_nexthop_mtu; + + /* Namespace info */ + struct zebra_dplane_info zd_ns_info; + + /* Nexthops */ + struct nexthop_group zd_ng; + + /* "Previous" nexthops, used only in route updates without netlink */ + struct nexthop_group zd_old_ng; + + /* TODO -- use fixed array of nexthops, to avoid mallocs? */ + + /* Embedded list linkage */ + TAILQ_ENTRY(zebra_dplane_ctx) zd_q_entries; +}; + +/* + * Registration block for one dataplane provider. + */ +struct zebra_dplane_provider { + /* Name */ + char dp_name[DPLANE_PROVIDER_NAMELEN + 1]; + + /* Priority, for ordering among providers */ + uint8_t dp_priority; + + /* Id value */ + uint32_t dp_id; + + dplane_provider_process_fp dp_fp; + + dplane_provider_fini_fp dp_fini; + + _Atomic uint64_t dp_in_counter; + _Atomic uint64_t dp_error_counter; + + /* Embedded list linkage */ + TAILQ_ENTRY(zebra_dplane_provider) dp_q_providers; + +}; + +/* + * Globals + */ +static struct zebra_dplane_globals { + /* Mutex to control access to dataplane components */ + pthread_mutex_t dg_mutex; + + /* Results callback registered by zebra 'core' */ + dplane_results_fp dg_results_cb; + + /* Sentinel for beginning of shutdown */ + volatile bool dg_is_shutdown; + + /* Sentinel for end of shutdown */ + volatile bool dg_run; + + /* Route-update context queue inbound to the dataplane */ + TAILQ_HEAD(zdg_ctx_q, zebra_dplane_ctx) dg_route_ctx_q; + + /* Ordered list of providers */ + TAILQ_HEAD(zdg_prov_q, zebra_dplane_provider) dg_providers_q; + + /* Counter used to assign internal ids to providers */ + uint32_t dg_provider_id; + + /* Limit number of pending, unprocessed updates */ + _Atomic uint32_t dg_max_queued_updates; + + _Atomic uint64_t dg_routes_in; + _Atomic uint32_t dg_routes_queued; + _Atomic uint32_t dg_routes_queued_max; + _Atomic uint64_t dg_route_errors; + + /* Event-delivery context 'master' for the dplane */ + struct thread_master *dg_master; + + /* Event/'thread' pointer for queued updates */ + struct thread *dg_t_update; + + /* Event pointer for pending shutdown check loop */ + struct thread *dg_t_shutdown_check; + +} zdplane_info; + +/* + * Lock and unlock for interactions with the zebra 'core' + */ +#define DPLANE_LOCK() pthread_mutex_lock(&zdplane_info.dg_mutex) + +#define DPLANE_UNLOCK() pthread_mutex_unlock(&zdplane_info.dg_mutex) + +/* Prototypes */ +static int dplane_route_process(struct thread *event); + +/* + * Public APIs + */ + +/* + * Allocate a dataplane update context + */ +static struct zebra_dplane_ctx *dplane_ctx_alloc(void) +{ + struct zebra_dplane_ctx *p; + + /* TODO -- just alloc'ing memory, but would like to maintain + * a pool + */ + p = XCALLOC(MTYPE_DP_CTX, sizeof(struct zebra_dplane_ctx)); + + return p; +} + +/* + * Free a dataplane results context. + */ +static void dplane_ctx_free(struct zebra_dplane_ctx **pctx) +{ + if (pctx) { + DPLANE_CTX_VALID(*pctx); + + /* TODO -- just freeing memory, but would like to maintain + * a pool + */ + + /* Free embedded nexthops */ + if ((*pctx)->zd_ng.nexthop) { + /* This deals with recursive nexthops too */ + nexthops_free((*pctx)->zd_ng.nexthop); + } + + if ((*pctx)->zd_old_ng.nexthop) { + /* This deals with recursive nexthops too */ + nexthops_free((*pctx)->zd_old_ng.nexthop); + } + + XFREE(MTYPE_DP_CTX, *pctx); + *pctx = NULL; + } +} + +/* + * Return a context block to the dplane module after processing + */ +void dplane_ctx_fini(struct zebra_dplane_ctx **pctx) +{ + /* TODO -- enqueue for next provider; for now, just free */ + dplane_ctx_free(pctx); +} + +/* Enqueue a context block */ +void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q, + const struct zebra_dplane_ctx *ctx) +{ + TAILQ_INSERT_TAIL(q, (struct zebra_dplane_ctx *)ctx, zd_q_entries); +} + +/* Dequeue a context block from the head of a list */ +void dplane_ctx_dequeue(struct dplane_ctx_q *q, struct zebra_dplane_ctx **ctxp) +{ + struct zebra_dplane_ctx *ctx = TAILQ_FIRST(q); + + if (ctx) + TAILQ_REMOVE(q, ctx, zd_q_entries); + + *ctxp = ctx; +} + +/* + * Accessors for information from the context object + */ +enum zebra_dplane_result dplane_ctx_get_status( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_status; +} + +enum dplane_op_e dplane_ctx_get_op(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_op; +} + +const char *dplane_op2str(enum dplane_op_e op) +{ + const char *ret = "UNKNOWN"; + + switch (op) { + case DPLANE_OP_NONE: + ret = "NONE"; + break; + + /* Route update */ + case DPLANE_OP_ROUTE_INSTALL: + ret = "ROUTE_INSTALL"; + break; + case DPLANE_OP_ROUTE_UPDATE: + ret = "ROUTE_UPDATE"; + break; + case DPLANE_OP_ROUTE_DELETE: + ret = "ROUTE_DELETE"; + break; + + }; + + return ret; +} + +const char *dplane_res2str(enum zebra_dplane_result res) +{ + const char *ret = ""; + + switch (res) { + case ZEBRA_DPLANE_REQUEST_FAILURE: + ret = "FAILURE"; + break; + case ZEBRA_DPLANE_REQUEST_QUEUED: + ret = "QUEUED"; + break; + case ZEBRA_DPLANE_REQUEST_SUCCESS: + ret = "SUCCESS"; + break; + }; + + return ret; +} + +const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &(ctx->zd_dest); +} + +/* Source prefix is a little special - return NULL for "no src prefix" */ +const struct prefix *dplane_ctx_get_src(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + if (ctx->zd_src.prefixlen == 0 && + IN6_IS_ADDR_UNSPECIFIED(&(ctx->zd_src.u.prefix6))) { + return NULL; + } else { + return &(ctx->zd_src); + } +} + +bool dplane_ctx_is_update(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_is_update; +} + +uint32_t dplane_ctx_get_seq(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_seq; +} + +uint32_t dplane_ctx_get_old_seq(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_old_seq; +} + +vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_vrf_id; +} + +int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_type; +} + +int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_old_type; +} + +afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_afi; +} + +safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_safi; +} + +uint32_t dplane_ctx_get_table(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_table_id; +} + +route_tag_t dplane_ctx_get_tag(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_tag; +} + +route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_old_tag; +} + +uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_instance; +} + +uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_instance; +} + +uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_metric; +} + +uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_old_metric; +} + +uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_mtu; +} + +uint32_t dplane_ctx_get_nh_mtu(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_nexthop_mtu; +} + +uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_distance; +} + +uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return ctx->zd_old_distance; +} + +const struct nexthop_group *dplane_ctx_get_ng( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &(ctx->zd_ng); +} + +const struct nexthop_group *dplane_ctx_get_old_ng( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &(ctx->zd_old_ng); +} + +const struct zebra_dplane_info *dplane_ctx_get_ns( + const struct zebra_dplane_ctx *ctx) +{ + DPLANE_CTX_VALID(ctx); + + return &(ctx->zd_ns_info); +} + +/* + * End of dplane context accessors + */ + +/* + * Retrieve the limit on the number of pending, unprocessed updates. + */ +uint32_t dplane_get_in_queue_limit(void) +{ + return atomic_load_explicit(&zdplane_info.dg_max_queued_updates, + memory_order_relaxed); +} + +/* + * Configure limit on the number of pending, queued updates. + */ +void dplane_set_in_queue_limit(uint32_t limit, bool set) +{ + /* Reset to default on 'unset' */ + if (!set) + limit = DPLANE_DEFAULT_MAX_QUEUED; + + atomic_store_explicit(&zdplane_info.dg_max_queued_updates, limit, + memory_order_relaxed); +} + +/* + * Retrieve the current queue depth of incoming, unprocessed updates + */ +uint32_t dplane_get_in_queue_len(void) +{ + return atomic_load_explicit(&zdplane_info.dg_routes_queued, + memory_order_seq_cst); +} + +/* + * Initialize a context block for a route update from zebra data structs. + */ +static int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, + enum dplane_op_e op, + struct route_node *rn, + struct route_entry *re) +{ + int ret = EINVAL; + const struct route_table *table = NULL; + const rib_table_info_t *info; + const struct prefix *p, *src_p; + struct zebra_ns *zns; + struct zebra_vrf *zvrf; + struct nexthop *nexthop; + + if (!ctx || !rn || !re) + goto done; + + ctx->zd_op = op; + + ctx->zd_type = re->type; + ctx->zd_old_type = re->type; + + /* Prefixes: dest, and optional source */ + srcdest_rnode_prefixes(rn, &p, &src_p); + + prefix_copy(&(ctx->zd_dest), p); + + if (src_p) + prefix_copy(&(ctx->zd_src), src_p); + else + memset(&(ctx->zd_src), 0, sizeof(ctx->zd_src)); + + ctx->zd_table_id = re->table; + + ctx->zd_metric = re->metric; + ctx->zd_old_metric = re->metric; + ctx->zd_vrf_id = re->vrf_id; + ctx->zd_mtu = re->mtu; + ctx->zd_nexthop_mtu = re->nexthop_mtu; + ctx->zd_instance = re->instance; + ctx->zd_tag = re->tag; + ctx->zd_old_tag = re->tag; + ctx->zd_distance = re->distance; + + table = srcdest_rnode_table(rn); + info = table->info; + + ctx->zd_afi = info->afi; + ctx->zd_safi = info->safi; + + /* Extract ns info - can't use pointers to 'core' structs */ + zvrf = vrf_info_lookup(re->vrf_id); + zns = zvrf->zns; + + zebra_dplane_info_from_zns(&(ctx->zd_ns_info), zns, true /*is_cmd*/); + +#if defined(HAVE_NETLINK) + /* Increment message counter after copying to context struct - may need + * two messages in some 'update' cases. + */ + if (op == DPLANE_OP_ROUTE_UPDATE) + zns->netlink_cmd.seq += 2; + else + zns->netlink_cmd.seq++; +#endif /* NETLINK*/ + + /* Copy nexthops; recursive info is included too */ + copy_nexthops(&(ctx->zd_ng.nexthop), re->ng.nexthop, NULL); + + /* TODO -- maybe use array of nexthops to avoid allocs? */ + + /* Ensure that the dplane's nexthop flag is clear. */ + for (ALL_NEXTHOPS(ctx->zd_ng, nexthop)) + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + + /* Trying out the sequence number idea, so we can try to detect + * when a result is stale. + */ + re->dplane_sequence++; + ctx->zd_seq = re->dplane_sequence; + + ret = AOK; + +done: + return ret; +} + +/* + * Enqueue a new route update, + * and ensure an event is active for the dataplane thread. + */ +static int dplane_route_enqueue(struct zebra_dplane_ctx *ctx) +{ + int ret = EINVAL; + uint32_t high, curr; + + /* Enqueue for processing by the dataplane thread */ + DPLANE_LOCK(); + { + TAILQ_INSERT_TAIL(&zdplane_info.dg_route_ctx_q, ctx, + zd_q_entries); + } + DPLANE_UNLOCK(); + + curr = atomic_add_fetch_explicit( +#ifdef __clang__ + /* TODO -- issue with the clang atomic/intrinsics currently; + * casting away the 'Atomic'-ness of the variable works. + */ + (uint32_t *)&(zdplane_info.dg_routes_queued), +#else + &(zdplane_info.dg_routes_queued), +#endif + 1, memory_order_seq_cst); + + /* Maybe update high-water counter also */ + high = atomic_load_explicit(&zdplane_info.dg_routes_queued_max, + memory_order_seq_cst); + while (high < curr) { + if (atomic_compare_exchange_weak_explicit( + &zdplane_info.dg_routes_queued_max, + &high, curr, + memory_order_seq_cst, + memory_order_seq_cst)) + break; + } + + /* Ensure that an event for the dataplane thread is active */ + thread_add_event(zdplane_info.dg_master, dplane_route_process, NULL, 0, + &zdplane_info.dg_t_update); + + ret = AOK; + + return ret; +} + +/* + * Attempt to dequeue a route-update block + */ +static struct zebra_dplane_ctx *dplane_route_dequeue(void) +{ + struct zebra_dplane_ctx *ctx = NULL; + + DPLANE_LOCK(); + { + ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q); + if (ctx) { + TAILQ_REMOVE(&zdplane_info.dg_route_ctx_q, + ctx, zd_q_entries); + } + } + DPLANE_UNLOCK(); + + return ctx; +} + +/* + * Utility that prepares a route update and enqueues it for processing + */ +static enum zebra_dplane_result +dplane_route_update_internal(struct route_node *rn, + struct route_entry *re, + struct route_entry *old_re, + enum dplane_op_e op) +{ + enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE; + int ret = EINVAL; + struct zebra_dplane_ctx *ctx = NULL; + + /* Obtain context block */ + ctx = dplane_ctx_alloc(); + if (ctx == NULL) { + ret = ENOMEM; + goto done; + } + + /* Init context with info from zebra data structs */ + ret = dplane_ctx_route_init(ctx, op, rn, re); + if (ret == AOK) { + /* Capture some extra info for update case + * where there's a different 'old' route. + */ + if ((op == DPLANE_OP_ROUTE_UPDATE) && + old_re && (old_re != re)) { + ctx->zd_is_update = true; + + old_re->dplane_sequence++; + ctx->zd_old_seq = old_re->dplane_sequence; + + ctx->zd_old_tag = old_re->tag; + ctx->zd_old_type = old_re->type; + ctx->zd_old_instance = old_re->instance; + ctx->zd_old_distance = old_re->distance; + ctx->zd_old_metric = old_re->metric; + +#ifndef HAVE_NETLINK + /* For bsd, capture previous re's nexthops too, sigh. + * We'll need these to do per-nexthop deletes. + */ + copy_nexthops(&(ctx->zd_old_ng.nexthop), + old_re->ng.nexthop, NULL); +#endif /* !HAVE_NETLINK */ + } + + /* Enqueue context for processing */ + ret = dplane_route_enqueue(ctx); + } + +done: + /* Update counter */ + atomic_fetch_add_explicit(&zdplane_info.dg_routes_in, 1, + memory_order_relaxed); + + if (ret == AOK) + result = ZEBRA_DPLANE_REQUEST_QUEUED; + else if (ctx) { + atomic_fetch_add_explicit(&zdplane_info.dg_route_errors, 1, + memory_order_relaxed); + dplane_ctx_free(&ctx); + } + + return result; +} + +/* + * Enqueue a route 'add' for the dataplane. + */ +enum zebra_dplane_result dplane_route_add(struct route_node *rn, + struct route_entry *re) +{ + enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; + + if (rn == NULL || re == NULL) + goto done; + + ret = dplane_route_update_internal(rn, re, NULL, + DPLANE_OP_ROUTE_INSTALL); + +done: + return ret; +} + +/* + * Enqueue a route update for the dataplane. + */ +enum zebra_dplane_result dplane_route_update(struct route_node *rn, + struct route_entry *re, + struct route_entry *old_re) +{ + enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; + + if (rn == NULL || re == NULL) + goto done; + + ret = dplane_route_update_internal(rn, re, old_re, + DPLANE_OP_ROUTE_UPDATE); +done: + return ret; +} + +/* + * Enqueue a route removal for the dataplane. + */ +enum zebra_dplane_result dplane_route_delete(struct route_node *rn, + struct route_entry *re) +{ + enum zebra_dplane_result ret = ZEBRA_DPLANE_REQUEST_FAILURE; + + if (rn == NULL || re == NULL) + goto done; + + ret = dplane_route_update_internal(rn, re, NULL, + DPLANE_OP_ROUTE_DELETE); + +done: + return ret; +} + +/* + * Event handler function for routing updates + */ +static int dplane_route_process(struct thread *event) +{ + enum zebra_dplane_result res; + struct zebra_dplane_ctx *ctx; + + while (1) { + /* Check for shutdown */ + if (!zdplane_info.dg_run) + break; + + /* TODO -- limit number of updates per cycle? */ + ctx = dplane_route_dequeue(); + if (ctx == NULL) + break; + + /* Update counter */ + atomic_fetch_sub_explicit(&zdplane_info.dg_routes_queued, 1, + memory_order_relaxed); + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + char dest_str[PREFIX_STRLEN]; + + prefix2str(dplane_ctx_get_dest(ctx), + dest_str, sizeof(dest_str)); + + zlog_debug("%u:%s Dplane route update ctx %p op %s", + dplane_ctx_get_vrf(ctx), dest_str, + ctx, dplane_op2str(dplane_ctx_get_op(ctx))); + } + + /* TODO -- support series of providers */ + + /* Initially, just doing kernel-facing update here */ + res = kernel_route_update(ctx); + + if (res != ZEBRA_DPLANE_REQUEST_SUCCESS) + atomic_fetch_add_explicit(&zdplane_info.dg_route_errors, + 1, memory_order_relaxed); + + ctx->zd_status = res; + + /* Enqueue result to zebra main context */ + zdplane_info.dg_results_cb(ctx); + + ctx = NULL; + } + + return 0; +} + +/* + * Handler for 'show dplane' + */ +int dplane_show_helper(struct vty *vty, bool detailed) +{ + uint64_t queued, limit, queue_max, errs, incoming; + + /* Using atomics because counters are being changed in different + * contexts. + */ + incoming = atomic_load_explicit(&zdplane_info.dg_routes_in, + memory_order_relaxed); + limit = atomic_load_explicit(&zdplane_info.dg_max_queued_updates, + memory_order_relaxed); + queued = atomic_load_explicit(&zdplane_info.dg_routes_queued, + memory_order_relaxed); + queue_max = atomic_load_explicit(&zdplane_info.dg_routes_queued_max, + memory_order_relaxed); + errs = atomic_load_explicit(&zdplane_info.dg_route_errors, + memory_order_relaxed); + + vty_out(vty, "Route updates: %"PRIu64"\n", incoming); + vty_out(vty, "Route update errors: %"PRIu64"\n", errs); + vty_out(vty, "Route update queue limit: %"PRIu64"\n", limit); + vty_out(vty, "Route update queue depth: %"PRIu64"\n", queued); + vty_out(vty, "Route update queue max: %"PRIu64"\n", queue_max); + + return CMD_SUCCESS; +} + +/* + * Handler for 'show dplane providers' + */ +int dplane_show_provs_helper(struct vty *vty, bool detailed) +{ + vty_out(vty, "Zebra dataplane providers:%s\n", + (detailed ? " (detailed)" : "")); + + return CMD_SUCCESS; +} + +/* + * Provider registration + */ +int dplane_provider_register(const char *name, + enum dplane_provider_prio_e prio, + dplane_provider_process_fp fp, + dplane_provider_fini_fp fini_fp) +{ + int ret = 0; + struct zebra_dplane_provider *p, *last; + + /* Validate */ + if (fp == NULL) { + ret = EINVAL; + goto done; + } + + if (prio <= DPLANE_PRIO_NONE || + prio > DPLANE_PRIO_LAST) { + ret = EINVAL; + goto done; + } + + /* Allocate and init new provider struct */ + p = XCALLOC(MTYPE_DP_PROV, sizeof(struct zebra_dplane_provider)); + if (p == NULL) { + ret = ENOMEM; + goto done; + } + + strncpy(p->dp_name, name, DPLANE_PROVIDER_NAMELEN); + p->dp_name[DPLANE_PROVIDER_NAMELEN] = '\0'; /* Belt-and-suspenders */ + + p->dp_priority = prio; + p->dp_fp = fp; + p->dp_fini = fini_fp; + + /* Lock the lock - the dplane pthread may be running */ + DPLANE_LOCK(); + + p->dp_id = ++zdplane_info.dg_provider_id; + + /* Insert into list ordered by priority */ + TAILQ_FOREACH(last, &zdplane_info.dg_providers_q, dp_q_providers) { + if (last->dp_priority > p->dp_priority) + break; + } + + if (last) + TAILQ_INSERT_BEFORE(last, p, dp_q_providers); + else + TAILQ_INSERT_TAIL(&zdplane_info.dg_providers_q, p, + dp_q_providers); + + /* And unlock */ + DPLANE_UNLOCK(); + +done: + return ret; +} + +/* + * Zebra registers a results callback with the dataplane system + */ +int dplane_results_register(dplane_results_fp fp) +{ + zdplane_info.dg_results_cb = fp; + return AOK; +} + +/* + * Initialize the dataplane module during startup, internal/private version + */ +static void zebra_dplane_init_internal(struct zebra_t *zebra) +{ + memset(&zdplane_info, 0, sizeof(zdplane_info)); + + pthread_mutex_init(&zdplane_info.dg_mutex, NULL); + + TAILQ_INIT(&zdplane_info.dg_route_ctx_q); + TAILQ_INIT(&zdplane_info.dg_providers_q); + + zdplane_info.dg_max_queued_updates = DPLANE_DEFAULT_MAX_QUEUED; + + /* TODO -- register default kernel 'provider' during init */ + + zdplane_info.dg_run = true; + + /* TODO -- start dataplane pthread. We're using the zebra + * core/main thread temporarily + */ + zdplane_info.dg_master = zebra->master; +} + +/* Indicates zebra shutdown/exit is in progress. Some operations may be + * simplified or skipped during shutdown processing. + */ +bool dplane_is_in_shutdown(void) +{ + return zdplane_info.dg_is_shutdown; +} + +/* + * Early or pre-shutdown, de-init notification api. This runs pretty + * early during zebra shutdown, as a signal to stop new work and prepare + * for updates generated by shutdown/cleanup activity, as zebra tries to + * remove everything it's responsible for. + * NB: This runs in the main zebra thread context. + */ +void zebra_dplane_pre_finish(void) +{ + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Zebra dataplane pre-fini called"); + + zdplane_info.dg_is_shutdown = true; + + /* Notify provider(s) of pending shutdown */ +} + +/* + * Utility to determine whether work remains enqueued within the dplane; + * used during system shutdown processing. + */ +static bool dplane_work_pending(void) +{ + struct zebra_dplane_ctx *ctx; + + /* TODO -- just checking incoming/pending work for now */ + DPLANE_LOCK(); + { + ctx = TAILQ_FIRST(&zdplane_info.dg_route_ctx_q); + } + DPLANE_UNLOCK(); + + return (ctx != NULL); +} + +/* + * Shutdown-time intermediate callback, used to determine when all pending + * in-flight updates are done. If there's still work to do, reschedules itself. + * If all work is done, schedules an event to the main zebra thread for + * final zebra shutdown. + * This runs in the dplane pthread context. + */ +static int dplane_check_shutdown_status(struct thread *event) +{ + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Zebra dataplane shutdown status check called"); + + if (dplane_work_pending()) { + /* Reschedule dplane check on a short timer */ + thread_add_timer_msec(zdplane_info.dg_master, + dplane_check_shutdown_status, + NULL, 100, + &zdplane_info.dg_t_shutdown_check); + + /* TODO - give up and stop waiting after a short time? */ + + } else { + /* We appear to be done - schedule a final callback event + * for the zebra main pthread. + */ + thread_add_event(zebrad.master, zebra_finalize, NULL, 0, NULL); + } + + return 0; +} + +/* + * Shutdown, de-init api. This runs pretty late during shutdown, + * after zebra has tried to free/remove/uninstall all routes during shutdown. + * At this point, dplane work may still remain to be done, so we can't just + * blindly terminate. If there's still work to do, we'll periodically check + * and when done, we'll enqueue a task to the zebra main thread for final + * termination processing. + * + * NB: This runs in the main zebra thread context. + */ +void zebra_dplane_finish(void) +{ + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Zebra dataplane fini called"); + + thread_add_event(zdplane_info.dg_master, + dplane_check_shutdown_status, NULL, 0, + &zdplane_info.dg_t_shutdown_check); +} + +/* + * Final phase of shutdown, after all work enqueued to dplane has been + * processed. This is called from the zebra main pthread context. + */ +void zebra_dplane_shutdown(void) +{ + if (IS_ZEBRA_DEBUG_DPLANE) + zlog_debug("Zebra dataplane shutdown called"); + + /* Stop dplane thread, if it's running */ + + zdplane_info.dg_run = false; + + THREAD_OFF(zdplane_info.dg_t_update); + + /* TODO */ + /* frr_pthread_stop(...) */ + + /* Notify provider(s) of final shutdown */ + + /* Clean-up provider objects */ + + /* Clean queue(s) */ +} + +/* + * Initialize the dataplane module at startup; called by zebra rib_init() + */ +void zebra_dplane_init(void) +{ + zebra_dplane_init_internal(&zebrad); +} diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h index 7cbef7453c..999e0f39e4 100644 --- a/zebra/zebra_dplane.h +++ b/zebra/zebra_dplane.h @@ -20,24 +20,22 @@ #ifndef _ZEBRA_DPLANE_H #define _ZEBRA_DPLANE_H 1 -#include "zebra.h" -#include "zserv.h" -#include "prefix.h" -#include "nexthop.h" -#include "nexthop_group.h" +#include "lib/zebra.h" +#include "lib/prefix.h" +#include "lib/nexthop.h" +#include "lib/nexthop_group.h" +#include "lib/openbsd-queue.h" +#include "zebra/zebra_ns.h" +#include "zebra/rib.h" +#include "zebra/zserv.h" -/* - * API between the zebra dataplane system and the main zebra processing - * context. - */ - /* Key netlink info from zebra ns */ struct zebra_dplane_info { ns_id_t ns_id; #if defined(HAVE_NETLINK) - uint32_t nl_pid; + struct nlsock nls; bool is_cmd; #endif }; @@ -52,21 +50,13 @@ zebra_dplane_info_from_zns(struct zebra_dplane_info *zns_info, #if defined(HAVE_NETLINK) zns_info->is_cmd = is_cmd; if (is_cmd) { - zns_info->nl_pid = zns->netlink_cmd.snl.nl_pid; + zns_info->nls = zns->netlink_cmd; } else { - zns_info->nl_pid = zns->netlink.snl.nl_pid; + zns_info->nls = zns->netlink; } #endif /* NETLINK */ } -/* - * Enqueue a route install or update for the dataplane. - */ - -/* - * Enqueue a route removal for the dataplane. - */ - /* * Result codes used when returning status back to the main zebra context. */ @@ -96,4 +86,191 @@ enum zebra_dplane_result { ZEBRA_DPLANE_REQUEST_FAILURE, }; +/* + * API between the zebra dataplane system and the main zebra processing + * context. + */ + +/* + * Enqueue a route install or update for the dataplane. + */ +enum dplane_op_e { + DPLANE_OP_NONE = 0, + + /* Route update */ + DPLANE_OP_ROUTE_INSTALL, + DPLANE_OP_ROUTE_UPDATE, + DPLANE_OP_ROUTE_DELETE, + +}; + +/* + * The dataplane context struct is used to exchange info between the main zebra + * context and the dataplane module(s). If these are two independent pthreads, + * they cannot share existing global data structures safely. + */ + +/* Define a tailq list type for context blocks. The list is exposed/public, + * but the internal linkage in the context struct is private, so there + * are accessor apis that support enqueue and dequeue. + */ +TAILQ_HEAD(dplane_ctx_q, zebra_dplane_ctx); + +/* Return a dataplane results context block after use; the caller's pointer will + * be cleared. + */ +void dplane_ctx_fini(struct zebra_dplane_ctx **pctx); + +/* Enqueue a context block to caller's tailq. This just exists so that the + * context struct can remain opaque. + */ +void dplane_ctx_enqueue_tail(struct dplane_ctx_q *q, + const struct zebra_dplane_ctx *ctx); + +/* Dequeue a context block from the head of caller's tailq */ +void dplane_ctx_dequeue(struct dplane_ctx_q *q, struct zebra_dplane_ctx **ctxp); + +/* + * Accessors for information from the context object + */ +enum zebra_dplane_result dplane_ctx_get_status( + const struct zebra_dplane_ctx *ctx); +const char *dplane_res2str(enum zebra_dplane_result res); + +enum dplane_op_e dplane_ctx_get_op(const struct zebra_dplane_ctx *ctx); +const char *dplane_op2str(enum dplane_op_e op); + +const struct prefix *dplane_ctx_get_dest(const struct zebra_dplane_ctx *ctx); + +/* Source prefix is a little special - use convention to return NULL + * to mean "no src prefix" + */ +const struct prefix *dplane_ctx_get_src(const struct zebra_dplane_ctx *ctx); + +bool dplane_ctx_is_update(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_seq(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_old_seq(const struct zebra_dplane_ctx *ctx); +vrf_id_t dplane_ctx_get_vrf(const struct zebra_dplane_ctx *ctx); +int dplane_ctx_get_type(const struct zebra_dplane_ctx *ctx); +int dplane_ctx_get_old_type(const struct zebra_dplane_ctx *ctx); +afi_t dplane_ctx_get_afi(const struct zebra_dplane_ctx *ctx); +safi_t dplane_ctx_get_safi(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_table(const struct zebra_dplane_ctx *ctx); +route_tag_t dplane_ctx_get_tag(const struct zebra_dplane_ctx *ctx); +route_tag_t dplane_ctx_get_old_tag(const struct zebra_dplane_ctx *ctx); +uint16_t dplane_ctx_get_instance(const struct zebra_dplane_ctx *ctx); +uint16_t dplane_ctx_get_old_instance(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_metric(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_old_metric(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_mtu(const struct zebra_dplane_ctx *ctx); +uint32_t dplane_ctx_get_nh_mtu(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx); +uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx); + +const struct nexthop_group *dplane_ctx_get_ng( + const struct zebra_dplane_ctx *ctx); +const struct nexthop_group *dplane_ctx_get_old_ng( + const struct zebra_dplane_ctx *ctx); + +const struct zebra_dplane_info *dplane_ctx_get_ns( + const struct zebra_dplane_ctx *ctx); + +/* Indicates zebra shutdown/exit is in progress. Some operations may be + * simplified or skipped during shutdown processing. + */ +bool dplane_is_in_shutdown(void); + +/* + * Enqueue route change operations for the dataplane. + */ +enum zebra_dplane_result dplane_route_add(struct route_node *rn, + struct route_entry *re); + +enum zebra_dplane_result dplane_route_update(struct route_node *rn, + struct route_entry *re, + struct route_entry *old_re); + +enum zebra_dplane_result dplane_route_delete(struct route_node *rn, + struct route_entry *re); + +/* Retrieve the limit on the number of pending, unprocessed updates. */ +uint32_t dplane_get_in_queue_limit(void); + +/* Configure limit on the number of pending, queued updates. If 'unset', reset + * to default value. + */ +void dplane_set_in_queue_limit(uint32_t limit, bool set); + +/* Retrieve the current queue depth of incoming, unprocessed updates */ +uint32_t dplane_get_in_queue_len(void); + +/* + * Vty/cli apis + */ +int dplane_show_helper(struct vty *vty, bool detailed); +int dplane_show_provs_helper(struct vty *vty, bool detailed); + + +/* + * Dataplane providers: modules that consume dataplane events. + */ + +/* Support string name for a dataplane provider */ +#define DPLANE_PROVIDER_NAMELEN 64 + +/* Priority or ordering values for providers. The idea is that there may be + * some pre-processing, followed by an external or remote dataplane, + * followed by the kernel, followed by some post-processing step (such as + * the fpm output stream.) + */ +enum dplane_provider_prio_e { + DPLANE_PRIO_NONE = 0, + DPLANE_PRIO_PREPROCESS, + DPLANE_PRIO_PRE_KERNEL, + DPLANE_PRIO_KERNEL, + DPLANE_PRIO_POSTPROCESS, + DPLANE_PRIO_LAST +}; + +/* Provider's entry-point to process a context block */ +typedef int (*dplane_provider_process_fp)(struct zebra_dplane_ctx *ctx); + +/* Provider's entry-point for shutdown and cleanup */ +typedef int (*dplane_provider_fini_fp)(void); + +/* Provider registration */ +int dplane_provider_register(const char *name, + enum dplane_provider_prio_e prio, + dplane_provider_process_fp fp, + dplane_provider_fini_fp fini_fp); + +/* + * Results are returned to zebra core via a callback + */ +typedef int (*dplane_results_fp)(const struct zebra_dplane_ctx *ctx); + +/* + * Zebra registers a results callback with the dataplane. The callback is + * called in the dataplane thread context, so the expectation is that the + * context is queued (or that processing is very limited). + */ +int dplane_results_register(dplane_results_fp fp); + +/* + * Initialize the dataplane modules at zebra startup. This is currently called + * by the rib module. + */ +void zebra_dplane_init(void); + +/* Finalize/cleanup apis, one called early as shutdown is starting, + * one called late at the end of zebra shutdown, and then one called + * from the zebra main thread to stop the dplane thread free all resources. + * + * Zebra expects to try to clean up all vrfs and all routes during + * shutdown, so the dplane must be available until very late. + */ +void zebra_dplane_pre_finish(void); +void zebra_dplane_finish(void); +void zebra_dplane_shutdown(void); + #endif /* _ZEBRA_DPLANE_H */ diff --git a/zebra/zebra_memory.h b/zebra/zebra_memory.h index e3439d5f64..de55478de2 100644 --- a/zebra/zebra_memory.h +++ b/zebra/zebra_memory.h @@ -34,5 +34,7 @@ DECLARE_MTYPE(STATIC_ROUTE) DECLARE_MTYPE(RIB_DEST) DECLARE_MTYPE(RIB_TABLE_INFO) DECLARE_MTYPE(RNH) +DECLARE_MTYPE(DP_CTX) +DECLARE_MTYPE(DP_PROV) #endif /* _QUAGGA_ZEBRA_MEMORY_H */ 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_netns_id.c b/zebra/zebra_netns_id.c index 600d1d55c6..ea4b07a87d 100644 --- a/zebra/zebra_netns_id.c +++ b/zebra/zebra_netns_id.c @@ -220,46 +220,36 @@ ns_id_t zebra_ns_id_get(const char *netnspath) nlh = (struct nlmsghdr *)buf; /* message to analyse : NEWNSID response */ - len = ret; ret = 0; - do { - if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { - return_nsid = extract_nsid(nlh, buf); - if (return_nsid != NS_UNKNOWN) - break; - } else { - if (nlh->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = - (struct nlmsgerr - *)((char *)nlh - + NETLINK_ALIGN(sizeof( - struct - nlmsghdr))); + if (nlh->nlmsg_type >= NLMSG_MIN_TYPE) { + return_nsid = extract_nsid(nlh, buf); + } else { + if (nlh->nlmsg_type == NLMSG_ERROR) { + struct nlmsgerr *err = + (struct nlmsgerr + *)((char *)nlh + + NETLINK_ALIGN( + sizeof(struct nlmsghdr))); - ret = -1; - if (err->error < 0) - errno = -err->error; - else - errno = err->error; - if (errno == 0) { - /* request NEWNSID was successfull - * return EEXIST error to get GETNSID - */ - errno = EEXIST; - } - } else { - /* other errors ignored - * attempt to get nsid + ret = -1; + if (err->error < 0) + errno = -err->error; + else + errno = err->error; + if (errno == 0) { + /* request NEWNSID was successfull + * return EEXIST error to get GETNSID */ - ret = -1; errno = EEXIST; - break; } + } else { + /* other errors ignored + * attempt to get nsid + */ + ret = -1; + errno = EEXIST; } - len = len - NETLINK_ALIGN(nlh->nlmsg_len); - nlh = (struct nlmsghdr *)((char *)nlh - + NETLINK_ALIGN(nlh->nlmsg_len)); - } while (len != 0 && return_nsid != NS_UNKNOWN && ret == 0); + } if (ret <= 0) { if (errno != EEXIST && ret != 0) { diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c index 2608ffd7a1..4d2aefa236 100644 --- a/zebra/zebra_netns_notify.c +++ b/zebra/zebra_netns_notify.c @@ -353,8 +353,11 @@ void zebra_ns_notify_close(void) if (zebra_netns_notify_current->u.fd > 0) fd = zebra_netns_notify_current->u.fd; - thread_cancel(zebra_netns_notify_current); - /* auto-removal of inotify items */ + + if (zebra_netns_notify_current->master != NULL) + thread_cancel(zebra_netns_notify_current); + + /* auto-removal of notify items */ if (fd > 0) close(fd); } diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index e251b26be1..e65f23dc8a 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -44,28 +44,8 @@ extern struct zebra_privs_t zserv_privs; DEFINE_MTYPE(ZEBRA, ZEBRA_NS, "Zebra Name Space") -static inline int zebra_ns_table_entry_compare(const struct zebra_ns_table *e1, - const struct zebra_ns_table *e2); - -RB_GENERATE(zebra_ns_table_head, zebra_ns_table, zebra_ns_table_entry, - zebra_ns_table_entry_compare); - static struct zebra_ns *dzns; -static inline int zebra_ns_table_entry_compare(const struct zebra_ns_table *e1, - const struct zebra_ns_table *e2) -{ - if (e1->tableid < e2->tableid) - return -1; - if (e1->tableid > e2->tableid) - return 1; - if (e1->ns_id < e2->ns_id) - return -1; - if (e1->ns_id > e2->ns_id) - return 1; - return (e1->afi - e2->afi); -} - static int logicalrouter_config_write(struct vty *vty); struct zebra_ns *zebra_ns_lookup(ns_id_t ns_id) @@ -141,24 +121,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) zns->ns_id = ns_id; - zns->rules_hash = - hash_create_size(8, zebra_pbr_rules_hash_key, - zebra_pbr_rules_hash_equal, "Rules Hash"); - - zns->ipset_hash = - hash_create_size(8, zebra_pbr_ipset_hash_key, - zebra_pbr_ipset_hash_equal, "IPset Hash"); - - zns->ipset_entry_hash = - hash_create_size(8, zebra_pbr_ipset_entry_hash_key, - zebra_pbr_ipset_entry_hash_equal, - "IPset Hash Entry"); - - zns->iptable_hash = - hash_create_size(8, zebra_pbr_iptable_hash_key, - zebra_pbr_iptable_hash_equal, - "IPtable Hash Entry"); - #if defined(HAVE_RTADV) rtadv_init(zns); #endif @@ -173,123 +135,10 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) return 0; } -struct route_table *zebra_ns_find_table(struct zebra_ns *zns, uint32_t tableid, - afi_t afi) -{ - struct zebra_ns_table finder; - struct zebra_ns_table *znst; - - memset(&finder, 0, sizeof(finder)); - finder.afi = afi; - finder.tableid = tableid; - finder.ns_id = zns->ns_id; - znst = RB_FIND(zebra_ns_table_head, &zns->ns_tables, &finder); - - if (znst) - return znst->table; - else - return NULL; -} - -unsigned long zebra_ns_score_proto(uint8_t proto, unsigned short instance) -{ - struct zebra_ns *zns; - struct zebra_ns_table *znst; - unsigned long cnt = 0; - - zns = zebra_ns_lookup(NS_DEFAULT); - - RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) { - if (znst->ns_id != NS_DEFAULT) - continue; - cnt += rib_score_proto_table(proto, instance, znst->table); - } - return cnt; -} - -void zebra_ns_sweep_route(void) -{ - struct zebra_ns_table *znst; - struct zebra_ns *zns; - - zns = zebra_ns_lookup(NS_DEFAULT); - - RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) { - if (znst->ns_id != NS_DEFAULT) - continue; - rib_sweep_table(znst->table); - } -} - -struct route_table *zebra_ns_get_table(struct zebra_ns *zns, - struct zebra_vrf *zvrf, uint32_t tableid, - afi_t afi) -{ - struct zebra_ns_table finder; - struct zebra_ns_table *znst; - rib_table_info_t *info; - - memset(&finder, 0, sizeof(finder)); - finder.afi = afi; - finder.tableid = tableid; - finder.ns_id = zns->ns_id; - znst = RB_FIND(zebra_ns_table_head, &zns->ns_tables, &finder); - - if (znst) - return znst->table; - - znst = XCALLOC(MTYPE_ZEBRA_NS, sizeof(*znst)); - znst->tableid = tableid; - znst->afi = afi; - znst->ns_id = zns->ns_id; - znst->table = - (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); - - info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); - info->zvrf = zvrf; - info->afi = afi; - info->safi = SAFI_UNICAST; - route_table_set_info(znst->table, info); - znst->table->cleanup = zebra_rtable_node_cleanup; - - RB_INSERT(zebra_ns_table_head, &zns->ns_tables, znst); - return znst->table; -} - -static void zebra_ns_free_table(struct zebra_ns_table *znst) -{ - void *table_info; - - rib_close_table(znst->table); - - table_info = route_table_get_info(znst->table); - route_table_finish(znst->table); - XFREE(MTYPE_RIB_TABLE_INFO, table_info); - XFREE(MTYPE_ZEBRA_NS, znst); -} - int zebra_ns_disable(ns_id_t ns_id, void **info) { - struct zebra_ns_table *znst, *tmp; struct zebra_ns *zns = (struct zebra_ns *)(*info); - hash_clean(zns->rules_hash, zebra_pbr_rules_free); - hash_free(zns->rules_hash); - hash_clean(zns->ipset_entry_hash, zebra_pbr_ipset_entry_free); - hash_clean(zns->ipset_hash, zebra_pbr_ipset_free); - hash_free(zns->ipset_hash); - hash_free(zns->ipset_entry_hash); - hash_clean(zns->iptable_hash, - zebra_pbr_iptable_free); - hash_free(zns->iptable_hash); - - RB_FOREACH_SAFE (znst, zebra_ns_table_head, &zns->ns_tables, tmp) { - if (znst->ns_id != ns_id) - continue; - RB_REMOVE(zebra_ns_table_head, &zns->ns_tables, znst); - zebra_ns_free_table(znst); - } - route_table_finish(zns->if_table); zebra_vxlan_ns_disable(zns); #if defined(HAVE_RTADV) @@ -339,6 +188,7 @@ int zebra_ns_init(void) zebra_ns_notify_parse(); zebra_ns_notify_init(); } + return 0; } diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index ed70a34c0b..c1a9b41b8d 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -38,19 +38,6 @@ struct nlsock { }; #endif -struct zebra_ns_table { - RB_ENTRY(zebra_ns_table) zebra_ns_table_entry; - - uint32_t tableid; - afi_t afi; - ns_id_t ns_id; - - struct route_table *table; -}; -RB_HEAD(zebra_ns_table_head, zebra_ns_table); -RB_PROTOTYPE(zebra_ns_table_head, zebra_ns_table, zebra_ns_table_entry, - zebra_ns_table_entry_compare) - struct zebra_ns { /* net-ns name. */ char name[VRF_NAMSIZ]; @@ -66,23 +53,6 @@ struct zebra_ns { struct route_table *if_table; - /* L3-VNI hash table (for EVPN). Only in default instance */ - struct hash *l3vni_table; - -#if defined(HAVE_RTADV) - struct rtadv rtadv; -#endif /* HAVE_RTADV */ - - struct zebra_ns_table_head ns_tables; - - struct hash *rules_hash; - - struct hash *ipset_hash; - - struct hash *ipset_entry_hash; - - struct hash *iptable_hash; - /* Back pointer */ struct ns *ns; }; @@ -94,13 +64,6 @@ int zebra_ns_enable(ns_id_t ns_id, void **info); int zebra_ns_disabled(struct ns *ns); int zebra_ns_disable(ns_id_t ns_id, void **info); -extern struct route_table *zebra_ns_find_table(struct zebra_ns *zns, - uint32_t tableid, afi_t afi); -extern struct route_table *zebra_ns_get_table(struct zebra_ns *zns, - struct zebra_vrf *zvrf, - uint32_t tableid, afi_t afi); int zebra_ns_config_write(struct vty *vty, struct ns *ns); -unsigned long zebra_ns_score_proto(uint8_t proto, unsigned short instance); -void zebra_ns_sweep_route(void); #endif diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 40f97765da..833306bcc4 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -26,6 +26,7 @@ #include #include +#include "zebra/zebra_router.h" #include "zebra/zebra_pbr.h" #include "zebra/rt.h" #include "zebra/zapi_msg.h" @@ -102,30 +103,24 @@ static const struct message fragment_value_str[] = { }; /* static function declarations */ -DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset, - uint64_t *pkts, uint64_t *bytes), - (zns, ipset, pkts, bytes)) +DEFINE_HOOK(zebra_pbr_ipset_entry_get_stat, + (struct zebra_pbr_ipset_entry *ipset, uint64_t *pkts, + uint64_t *bytes), + (ipset, pkts, bytes)) -DEFINE_HOOK(zebra_pbr_iptable_wrap_script_get_stat, (struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable, - uint64_t *pkts, uint64_t *bytes), - (zns, iptable, pkts, bytes)) +DEFINE_HOOK(zebra_pbr_iptable_get_stat, + (struct zebra_pbr_iptable *iptable, uint64_t *pkts, + uint64_t *bytes), + (iptable, pkts, bytes)) -DEFINE_HOOK(zebra_pbr_iptable_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_iptable *iptable), - (zns, cmd, iptable)); +DEFINE_HOOK(zebra_pbr_iptable_update, + (int cmd, struct zebra_pbr_iptable *iptable), (cmd, iptable)); -DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_ipset_entry *ipset), - (zns, cmd, ipset)); +DEFINE_HOOK(zebra_pbr_ipset_entry_update, + (int cmd, struct zebra_pbr_ipset_entry *ipset), (cmd, ipset)); -DEFINE_HOOK(zebra_pbr_ipset_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_ipset *ipset), - (zns, cmd, ipset)); +DEFINE_HOOK(zebra_pbr_ipset_update, + (int cmd, struct zebra_pbr_ipset *ipset), (cmd, ipset)); /* Private functions */ @@ -158,13 +153,16 @@ uint32_t zebra_pbr_rules_hash_key(void *arg) key = jhash_1word(rule->rule.filter.fwmark, key); else key = jhash_1word(0, key); + + key = jhash_1word(rule->vrf_id, key); + return jhash_3words(rule->rule.filter.src_port, rule->rule.filter.dst_port, prefix_hash_key(&rule->rule.filter.dst_ip), 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,42 +170,46 @@ 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; + if (r1->vrf_id != r2->vrf_id) + return false; + + return true; } struct pbr_rule_unique_lookup { struct zebra_pbr_rule *rule; uint32_t unique; struct interface *ifp; + vrf_id_t vrf_id; }; static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data) @@ -215,7 +217,9 @@ static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data) struct pbr_rule_unique_lookup *pul = data; struct zebra_pbr_rule *rule = b->data; - if (pul->unique == rule->rule.unique && pul->ifp == rule->ifp) { + if (pul->unique == rule->rule.unique + && pul->ifp == rule->ifp + && pul->vrf_id == rule->vrf_id) { pul->rule = rule; return HASHWALK_ABORT; } @@ -223,16 +227,16 @@ static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data) return HASHWALK_CONTINUE; } -static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns, - uint32_t unique, - struct interface *ifp) +static struct zebra_pbr_rule * +pbr_rule_lookup_unique(struct zebra_pbr_rule *zrule) { struct pbr_rule_unique_lookup pul; - pul.unique = unique; - pul.ifp = ifp; + pul.unique = zrule->rule.unique; + pul.ifp = zrule->ifp; pul.rule = NULL; - hash_walk(zns->rules_hash, &pbr_rule_lookup_unique_walker, &pul); + pul.vrf_id = zrule->vrf_id; + hash_walk(zrouter.rules_hash, &pbr_rule_lookup_unique_walker, &pul); return pul.rule; } @@ -240,15 +244,9 @@ static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns, void zebra_pbr_ipset_free(void *arg) { struct zebra_pbr_ipset *ipset; - struct zebra_ns *zns; ipset = (struct zebra_pbr_ipset *)arg; - if (vrf_is_backend_netns()) - zns = zebra_ns_lookup(ipset->vrf_id); - else - zns = zebra_ns_lookup(NS_DEFAULT); - hook_call(zebra_pbr_ipset_wrap_script_update, - zns, 0, ipset); + hook_call(zebra_pbr_ipset_update, 0, ipset); XFREE(MTYPE_TMP, ipset); } @@ -256,11 +254,12 @@ uint32_t zebra_pbr_ipset_hash_key(void *arg) { struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg; uint32_t *pnt = (uint32_t *)&ipset->ipset_name; + uint32_t key = jhash_1word(ipset->vrf_id, 0x63ab42de); - return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, 0x63ab42de); + return jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, key); } -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,29 +267,25 @@ 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 (r1->vrf_id != r2->vrf_id) + 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) { struct zebra_pbr_ipset_entry *ipset; - struct zebra_ns *zns; ipset = (struct zebra_pbr_ipset_entry *)arg; - if (ipset->backpointer && vrf_is_backend_netns()) { - struct zebra_pbr_ipset *ips = ipset->backpointer; - zns = zebra_ns_lookup((ns_id_t)ips->vrf_id); - } else - zns = zebra_ns_lookup(NS_DEFAULT); - hook_call(zebra_pbr_ipset_entry_wrap_script_update, - zns, 0, ipset); + hook_call(zebra_pbr_ipset_entry_update, 0, ipset); XFREE(MTYPE_TMP, ipset); } @@ -313,7 +308,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 +316,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) @@ -351,15 +346,9 @@ void zebra_pbr_iptable_free(void *arg) struct zebra_pbr_iptable *iptable; struct listnode *node, *nnode; char *name; - struct zebra_ns *zns; iptable = (struct zebra_pbr_iptable *)arg; - if (vrf_is_backend_netns()) - zns = zebra_ns_lookup((ns_id_t)iptable->vrf_id); - else - zns = zebra_ns_lookup(NS_DEFAULT); - hook_call(zebra_pbr_iptable_wrap_script_update, - zns, 0, iptable); + hook_call(zebra_pbr_iptable_update, 0, iptable); for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node, nnode, name)) { @@ -385,43 +374,47 @@ uint32_t zebra_pbr_iptable_hash_key(void *arg) key = jhash_1word(iptable->tcp_mask_flags, key); key = jhash_1word(iptable->dscp_value, key); key = jhash_1word(iptable->fragment, key); + key = jhash_1word(iptable->vrf_id, key); + return jhash_3words(iptable->filter_bm, iptable->type, 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; r1 = (const struct zebra_pbr_iptable *)arg1; r2 = (const struct zebra_pbr_iptable *)arg2; + if (r1->vrf_id != r2->vrf_id) + return 0; 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) @@ -438,30 +431,30 @@ static void *pbr_rule_alloc_intern(void *arg) return new; } -void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) +void zebra_pbr_add_rule(struct zebra_pbr_rule *rule) { struct zebra_pbr_rule *unique = - pbr_rule_lookup_unique(zns, rule->rule.unique, rule->ifp); + pbr_rule_lookup_unique(rule); - (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern); + (void)hash_get(zrouter.rules_hash, rule, pbr_rule_alloc_intern); (void)kernel_add_pbr_rule(rule); /* * Rule Replace semantics, if we have an old, install the * new rule, look above, and then delete the old */ if (unique) - zebra_pbr_del_rule(zns, unique); + zebra_pbr_del_rule(unique); } -void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) +void zebra_pbr_del_rule(struct zebra_pbr_rule *rule) { struct zebra_pbr_rule *lookup; - lookup = hash_lookup(zns->rules_hash, rule); + lookup = hash_lookup(zrouter.rules_hash, rule); (void)kernel_del_pbr_rule(rule); if (lookup) { - hash_release(zns->rules_hash, lookup); + hash_release(zrouter.rules_hash, lookup); XFREE(MTYPE_TMP, lookup); } else zlog_debug("%s: Rule being deleted we know nothing about", @@ -470,70 +463,60 @@ void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_rule *rule = b->data; int *sock = data; if (rule->sock == *sock) { (void)kernel_del_pbr_rule(rule); - hash_release(zns->rules_hash, rule); + hash_release(zrouter.rules_hash, rule); XFREE(MTYPE_TMP, rule); } } static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_ipset *ipset = b->data; int *sock = data; if (ipset->sock == *sock) { - hook_call(zebra_pbr_ipset_wrap_script_update, - zns, 0, ipset); - hash_release(zns->ipset_hash, ipset); + hook_call(zebra_pbr_ipset_update, 0, ipset); + hash_release(zrouter.ipset_hash, ipset); } } static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_ipset_entry *ipset = b->data; int *sock = data; if (ipset->sock == *sock) { - hook_call(zebra_pbr_ipset_entry_wrap_script_update, - zns, 0, ipset); - hash_release(zns->ipset_entry_hash, ipset); + hook_call(zebra_pbr_ipset_entry_update, 0, ipset); + hash_release(zrouter.ipset_entry_hash, ipset); } } static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data) { - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); struct zebra_pbr_iptable *iptable = b->data; int *sock = data; if (iptable->sock == *sock) { - hook_call(zebra_pbr_iptable_wrap_script_update, - zns, 0, iptable); - hash_release(zns->iptable_hash, iptable); + hook_call(zebra_pbr_iptable_update, 0, iptable); + hash_release(zrouter.iptable_hash, iptable); } } static int zebra_pbr_client_close_cleanup(struct zserv *client) { int sock = client->sock; - struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT); if (!sock) return 0; - hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock); - hash_iterate(zns->iptable_hash, - zebra_pbr_cleanup_iptable, &sock); - hash_iterate(zns->ipset_entry_hash, - zebra_pbr_cleanup_ipset_entry, &sock); - hash_iterate(zns->ipset_hash, - zebra_pbr_cleanup_ipset, &sock); + hash_iterate(zrouter.rules_hash, zebra_pbr_cleanup_rules, &sock); + hash_iterate(zrouter.iptable_hash, zebra_pbr_cleanup_iptable, &sock); + hash_iterate(zrouter.ipset_entry_hash, zebra_pbr_cleanup_ipset_entry, + &sock); + hash_iterate(zrouter.ipset_hash, zebra_pbr_cleanup_ipset, &sock); return 1; } @@ -556,29 +539,25 @@ static void *pbr_ipset_alloc_intern(void *arg) return new; } -void zebra_pbr_create_ipset(struct zebra_ns *zns, - struct zebra_pbr_ipset *ipset) +void zebra_pbr_create_ipset(struct zebra_pbr_ipset *ipset) { int ret; - (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern); - ret = hook_call(zebra_pbr_ipset_wrap_script_update, - zns, 1, ipset); + (void)hash_get(zrouter.ipset_hash, ipset, pbr_ipset_alloc_intern); + ret = hook_call(zebra_pbr_ipset_update, 1, ipset); kernel_pbr_ipset_add_del_status(ipset, ret ? ZEBRA_DPLANE_INSTALL_SUCCESS : ZEBRA_DPLANE_INSTALL_FAILURE); } -void zebra_pbr_destroy_ipset(struct zebra_ns *zns, - struct zebra_pbr_ipset *ipset) +void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset) { struct zebra_pbr_ipset *lookup; - lookup = hash_lookup(zns->ipset_hash, ipset); - hook_call(zebra_pbr_ipset_wrap_script_update, - zns, 0, ipset); + lookup = hash_lookup(zrouter.ipset_hash, ipset); + hook_call(zebra_pbr_ipset_update, 0, ipset); if (lookup) { - hash_release(zns->ipset_hash, lookup); + hash_release(zrouter.ipset_hash, lookup); XFREE(MTYPE_TMP, lookup); } else zlog_debug( @@ -611,8 +590,7 @@ static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg) return HASHWALK_CONTINUE; } -struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, - char *ipsetname) +struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(char *ipsetname) { struct pbr_ipset_name_lookup pinl; struct pbr_ipset_name_lookup *ptr = &pinl; @@ -622,7 +600,7 @@ struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup)); snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s", ipsetname); - hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr); + hash_walk(zrouter.ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr); return ptr->ipset; } @@ -640,30 +618,26 @@ static void *pbr_ipset_entry_alloc_intern(void *arg) return new; } -void zebra_pbr_add_ipset_entry(struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset) +void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry *ipset) { int ret; - (void)hash_get(zns->ipset_entry_hash, ipset, + (void)hash_get(zrouter.ipset_entry_hash, ipset, pbr_ipset_entry_alloc_intern); - ret = hook_call(zebra_pbr_ipset_entry_wrap_script_update, - zns, 1, ipset); + ret = hook_call(zebra_pbr_ipset_entry_update, 1, ipset); kernel_pbr_ipset_entry_add_del_status(ipset, ret ? ZEBRA_DPLANE_INSTALL_SUCCESS : ZEBRA_DPLANE_INSTALL_FAILURE); } -void zebra_pbr_del_ipset_entry(struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset) +void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset) { struct zebra_pbr_ipset_entry *lookup; - lookup = hash_lookup(zns->ipset_entry_hash, ipset); - hook_call(zebra_pbr_ipset_entry_wrap_script_update, - zns, 0, ipset); + lookup = hash_lookup(zrouter.ipset_entry_hash, ipset); + hook_call(zebra_pbr_ipset_entry_update, 0, ipset); if (lookup) { - hash_release(zns->ipset_entry_hash, lookup); + hash_release(zrouter.ipset_entry_hash, lookup); XFREE(MTYPE_TMP, lookup); } else zlog_debug("%s: IPSet being deleted we know nothing about", @@ -684,31 +658,28 @@ static void *pbr_iptable_alloc_intern(void *arg) return new; } -void zebra_pbr_add_iptable(struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable) +void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable) { int ret; - (void)hash_get(zns->iptable_hash, iptable, - pbr_iptable_alloc_intern); - ret = hook_call(zebra_pbr_iptable_wrap_script_update, zns, 1, iptable); + (void)hash_get(zrouter.iptable_hash, iptable, pbr_iptable_alloc_intern); + ret = hook_call(zebra_pbr_iptable_update, 1, iptable); kernel_pbr_iptable_add_del_status(iptable, ret ? ZEBRA_DPLANE_INSTALL_SUCCESS : ZEBRA_DPLANE_INSTALL_FAILURE); } -void zebra_pbr_del_iptable(struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable) +void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable) { struct zebra_pbr_iptable *lookup; - lookup = hash_lookup(zns->iptable_hash, iptable); - hook_call(zebra_pbr_iptable_wrap_script_update, zns, 0, iptable); + lookup = hash_lookup(zrouter.iptable_hash, iptable); + hook_call(zebra_pbr_iptable_update, 0, iptable); if (lookup) { struct listnode *node, *nnode; char *name; - hash_release(zns->iptable_hash, lookup); + hash_release(zrouter.iptable_hash, lookup); for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node, nnode, name)) { XFREE(MTYPE_PBR_IPTABLE_IFNAME, name); @@ -913,7 +884,6 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet, struct zebra_pbr_ipset_entry *zpie = (struct zebra_pbr_ipset_entry *)backet->data; uint64_t pkts = 0, bytes = 0; - struct zebra_ns *zns = unique->zns; int ret = 0; if (zpie->backpointer != zpi) @@ -971,8 +941,8 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet, } vty_out(vty, " (%u)\n", zpie->unique); - ret = hook_call(zebra_pbr_ipset_entry_wrap_script_get_stat, - zns, zpie, &pkts, &bytes); + ret = hook_call(zebra_pbr_ipset_entry_get_stat, zpie, &pkts, + &bytes); if (ret && pkts > 0) vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n", pkts, bytes); @@ -993,7 +963,7 @@ static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg) unique.vty = vty; unique.zpi = zpi; unique.zns = zns; - hash_walk(zns->ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb, + hash_walk(zrouter.ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb, &unique); vty_out(vty, "\n"); return HASHWALK_CONTINUE; @@ -1029,7 +999,7 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname) struct zebra_pbr_env_display uniqueipset; if (ipsetname) { - zpi = zebra_pbr_lookup_ipset_pername(zns, ipsetname); + zpi = zebra_pbr_lookup_ipset_pername(ipsetname); if (!zpi) { vty_out(vty, "No IPset %s found\n", ipsetname); return; @@ -1040,15 +1010,14 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname) unique.vty = vty; unique.zpi = zpi; unique.zns = zns; - hash_walk(zns->ipset_entry_hash, - zebra_pbr_show_ipset_entry_walkcb, - &unique); + hash_walk(zrouter.ipset_entry_hash, + zebra_pbr_show_ipset_entry_walkcb, &unique); return; } uniqueipset.zns = zns; uniqueipset.vty = vty; uniqueipset.name = NULL; - hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb, + hash_walk(zrouter.ipset_hash, zebra_pbr_show_ipset_walkcb, &uniqueipset); } @@ -1126,8 +1095,8 @@ static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, " not" : "", lookup_msg(fragment_value_str, iptable->fragment, val_str)); } - ret = hook_call(zebra_pbr_iptable_wrap_script_get_stat, - zns, iptable, &pkts, &bytes); + ret = hook_call(zebra_pbr_iptable_get_stat, iptable, &pkts, + &bytes); if (ret && pkts > 0) vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n", pkts, bytes); @@ -1136,7 +1105,7 @@ static void zebra_pbr_show_iptable_unit(struct zebra_pbr_iptable *iptable, prfl.fwmark = iptable->fwmark; prfl.ptr = NULL; - hash_walk(zns->rules_hash, + hash_walk(zrouter.rules_hash, &zebra_pbr_rule_lookup_fwmark_walkcb, &prfl); if (prfl.ptr) { struct zebra_pbr_rule *zpr = prfl.ptr; @@ -1174,8 +1143,7 @@ void zebra_pbr_show_iptable(struct vty *vty, char *iptable_name) env.vty = vty; env.zns = zns; env.name = iptable_name; - hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb, - &env); + hash_walk(zrouter.iptable_hash, zebra_pbr_show_iptable_walkcb, &env); } void zebra_pbr_iptable_update_interfacelist(struct stream *s, diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 3311af4d26..5b6c23896c 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -38,6 +38,8 @@ struct zebra_pbr_rule { struct pbr_rule rule; struct interface *ifp; + + vrf_id_t vrf_id; }; #define IS_RULE_FILTERING_ON_SRC_IP(r) \ @@ -151,23 +153,16 @@ extern const struct message icmp_typecode_str[]; const char *zebra_pbr_ipset_type2str(uint32_t type); -void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); -void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); -void zebra_pbr_create_ipset(struct zebra_ns *zns, - struct zebra_pbr_ipset *ipset); -void zebra_pbr_destroy_ipset(struct zebra_ns *zns, - struct zebra_pbr_ipset *ipset); -struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, - char *ipsetname); -void zebra_pbr_add_ipset_entry(struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset); -void zebra_pbr_del_ipset_entry(struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset); +void zebra_pbr_add_rule(struct zebra_pbr_rule *rule); +void zebra_pbr_del_rule(struct zebra_pbr_rule *rule); +void zebra_pbr_create_ipset(struct zebra_pbr_ipset *ipset); +void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset); +struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(char *ipsetname); +void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry *ipset); +void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset); -void zebra_pbr_add_iptable(struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable); -void zebra_pbr_del_iptable(struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable); +void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable); +void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable); /* * Install specified rule for a specific interface. @@ -213,7 +208,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 +217,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); @@ -240,26 +236,20 @@ extern void zebra_pbr_iptable_update_interfacelist(struct stream *s, size_t zebra_pbr_tcpflags_snprintf(char *buffer, size_t len, uint16_t tcp_val); -DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns, - struct zebra_pbr_ipset_entry *ipset, - uint64_t *pkts, uint64_t *bytes), - (zns, ipset, pkts, bytes)) -DECLARE_HOOK(zebra_pbr_iptable_wrap_script_get_stat, (struct zebra_ns *zns, - struct zebra_pbr_iptable *iptable, - uint64_t *pkts, uint64_t *bytes), - (zns, iptable, pkts, bytes)) -DECLARE_HOOK(zebra_pbr_iptable_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_iptable *iptable), - (zns, cmd, iptable)); +DECLARE_HOOK(zebra_pbr_ipset_entry_get_stat, + (struct zebra_pbr_ipset_entry *ipset, uint64_t *pkts, + uint64_t *bytes), + (ipset, pkts, bytes)) +DECLARE_HOOK(zebra_pbr_iptable_get_stat, + (struct zebra_pbr_iptable *iptable, uint64_t *pkts, + uint64_t *bytes), + (iptable, pkts, bytes)) +DECLARE_HOOK(zebra_pbr_iptable_update, + (int cmd, struct zebra_pbr_iptable *iptable), (cmd, iptable)); -DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_ipset_entry *ipset), - (zns, cmd, ipset)); -DECLARE_HOOK(zebra_pbr_ipset_wrap_script_update, (struct zebra_ns *zns, - int cmd, - struct zebra_pbr_ipset *ipset), - (zns, cmd, ipset)); +DECLARE_HOOK(zebra_pbr_ipset_entry_update, + (int cmd, struct zebra_pbr_ipset_entry *ipset), (cmd, ipset)); +DECLARE_HOOK(zebra_pbr_ipset_update, + (int cmd, struct zebra_pbr_ipset *ipset), (cmd, ipset)); #endif /* _ZEBRA_PBR_H */ diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index b711241611..e4a4adba05 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -1030,8 +1030,7 @@ int zebra_ptm_bfd_client_deregister(struct zserv *client) char tmp_buf[64]; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; - if (proto != ZEBRA_ROUTE_OSPF && proto != ZEBRA_ROUTE_BGP - && proto != ZEBRA_ROUTE_OSPF6 && proto != ZEBRA_ROUTE_PIM) + if (!IS_BFD_ENABLED_PROTOCOL(proto)) return 0; if (IS_ZEBRA_DEBUG_EVENT) @@ -1310,17 +1309,8 @@ static void zebra_ptm_send_clients(struct stream *msg) /* Send message to all running client daemons. */ for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) { - switch (client->proto) { - case ZEBRA_ROUTE_BGP: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_PIM: - break; - - default: - /* NOTHING: skip this daemon. */ + if (!IS_BFD_ENABLED_PROTOCOL(client->proto)) continue; - } zserv_send_message(client, msg); @@ -1341,23 +1331,9 @@ static int _zebra_ptm_bfd_client_deregister(struct zserv *zs) struct stream *msg; struct ptm_process *pp; - /* Filter daemons that must receive this treatment. */ - switch (zs->proto) { - case ZEBRA_ROUTE_BGP: - case ZEBRA_ROUTE_OSPF: - case ZEBRA_ROUTE_OSPF6: - case ZEBRA_ROUTE_PIM: - break; - - case ZEBRA_ROUTE_BFD: - /* Don't try to send BFDd messages to itself. */ + if (!IS_BFD_ENABLED_PROTOCOL(zs->proto)) return 0; - default: - /* Unsupported daemon. */ - return 0; - } - /* Find daemon pid by zebra connection pointer. */ pp = pp_lookup_byzs(zs); if (pp == NULL) { diff --git a/zebra/zebra_ptm.h b/zebra/zebra_ptm.h index ada4f7b4f7..d0cdaf0bce 100644 --- a/zebra/zebra_ptm.h +++ b/zebra/zebra_ptm.h @@ -59,6 +59,15 @@ struct zebra_ptm_cb { #define ZEBRA_IF_PTM_ENABLE_ON 1 #define ZEBRA_IF_PTM_ENABLE_UNSPEC 2 +#define IS_BFD_ENABLED_PROTOCOL(protocol) ( \ + (protocol) == ZEBRA_ROUTE_BGP || \ + (protocol) == ZEBRA_ROUTE_OSPF || \ + (protocol) == ZEBRA_ROUTE_OSPF6 || \ + (protocol) == ZEBRA_ROUTE_ISIS || \ + (protocol) == ZEBRA_ROUTE_PIM || \ + (protocol) == ZEBRA_ROUTE_OPENFABRIC \ +) + void zebra_ptm_init(void); void zebra_ptm_finish(void); int zebra_ptm_connect(struct thread *t); diff --git a/zebra/zebra_ptm_redistribute.c b/zebra/zebra_ptm_redistribute.c index 815f61d157..420105198b 100644 --- a/zebra/zebra_ptm_redistribute.c +++ b/zebra/zebra_ptm_redistribute.c @@ -24,6 +24,7 @@ #include "stream.h" #include "zebra/zserv.h" #include "zebra/zapi_msg.h" +#include "zebra/zebra_ptm.h" #include "zebra/zebra_ptm_redistribute.h" #include "zebra/zebra_memory.h" @@ -76,11 +77,7 @@ void zebra_interface_bfd_update(struct interface *ifp, struct prefix *dp, struct zserv *client; for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { - /* Supporting for OSPF, BGP and PIM */ - if (client->proto != ZEBRA_ROUTE_OSPF - && client->proto != ZEBRA_ROUTE_BGP - && client->proto != ZEBRA_ROUTE_OSPF6 - && client->proto != ZEBRA_ROUTE_PIM) + if (!IS_BFD_ENABLED_PROTOCOL(client->proto)) continue; /* Notify to the protocol daemons. */ @@ -110,11 +107,7 @@ void zebra_bfd_peer_replay_req(void) struct zserv *client; for (ALL_LIST_ELEMENTS(zebrad.client_list, node, nnode, client)) { - /* Supporting for BGP */ - if ((client->proto != ZEBRA_ROUTE_BGP) - && (client->proto != ZEBRA_ROUTE_OSPF) - && (client->proto != ZEBRA_ROUTE_OSPF6) - && (client->proto != ZEBRA_ROUTE_PIM)) + if (!IS_BFD_ENABLED_PROTOCOL(client->proto)) continue; /* Notify to the protocol daemons. */ diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index bdcf03a055..d55467c727 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -38,6 +38,7 @@ #include "vrf.h" #include "workqueue.h" +#include "zebra/zebra_router.h" #include "zebra/connected.h" #include "zebra/debug.h" #include "zebra/interface.h" @@ -52,6 +53,15 @@ #include "zebra/zebra_routemap.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_vxlan.h" +#include "zebra/zapi_msg.h" +#include "zebra/zebra_dplane.h" + +/* + * Event, list, and mutex for delivery of dataplane results + */ +static pthread_mutex_t dplane_mutex; +static struct thread *t_dplane; +static struct dplane_ctx_q rib_dplane_q; DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason), (rn, reason)) @@ -601,9 +611,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; } @@ -867,6 +888,9 @@ int rib_lookup_ipv4_route(struct prefix_ipv4 *p, union sockunion *qgate, #define RIB_SYSTEM_ROUTE(R) \ ((R)->type == ZEBRA_ROUTE_KERNEL || (R)->type == ZEBRA_ROUTE_CONNECT) +#define RIB_KERNEL_ROUTE(R) \ + ((R)->type == ZEBRA_ROUTE_KERNEL) + /* This function verifies reachability of one given nexthop, which can be * numbered or unnumbered, IPv4 or IPv6. The result is unconditionally stored * in nexthop->flags field. If the 4th parameter, 'set', is non-zero, @@ -886,6 +910,8 @@ static unsigned nexthop_active_check(struct route_node *rn, int family; char buf[SRCDEST2STR_BUFFER]; const struct prefix *p, *src_p; + struct zebra_vrf *zvrf; + srcdest_rnode_prefixes(rn, &p, &src_p); if (rn->p.family == AF_INET) @@ -949,7 +975,8 @@ static unsigned nexthop_active_check(struct route_node *rn, } /* XXX: What exactly do those checks do? Do we support - * e.g. IPv4 routes with IPv6 nexthops or vice versa? */ + * e.g. IPv4 routes with IPv6 nexthops or vice versa? + */ if (RIB_SYSTEM_ROUTE(re) || (family == AFI_IP && p->family != AF_INET) || (family == AFI_IP6 && p->family != AF_INET6)) return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -969,9 +996,16 @@ static unsigned nexthop_active_check(struct route_node *rn, memset(&nexthop->rmap_src.ipv6, 0, sizeof(union g_addr)); + zvrf = zebra_vrf_lookup_by_id(nexthop->vrf_id); + if (!zvrf) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("\t%s: zvrf is NULL", __PRETTY_FUNCTION__); + return CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); + } + /* It'll get set if required inside */ - ret = zebra_route_map_check(family, re->type, re->instance, p, nexthop, - nexthop->vrf_id, re->tag); + ret = zebra_route_map_check(family, re->type, re->instance, p, + nexthop, zvrf, re->tag); if (ret == RMAP_DENYMATCH) { if (IS_ZEBRA_DEBUG_RIB) { srcdest_rnode2str(rn, buf, sizeof(buf)); @@ -1002,6 +1036,7 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re, union g_addr prev_src; unsigned int prev_active, new_active, old_num_nh; ifindex_t prev_index; + old_num_nh = re->nexthop_active_num; re->nexthop_active_num = 0; @@ -1058,75 +1093,6 @@ int zebra_rib_labeled_unicast(struct route_entry *re) return 1; } -void kernel_route_rib_pass_fail(struct route_node *rn, const struct prefix *p, - struct route_entry *re, - enum zebra_dplane_status res) -{ - struct nexthop *nexthop; - char buf[PREFIX_STRLEN]; - rib_dest_t *dest; - - dest = rib_dest_from_rnode(rn); - - switch (res) { - case ZEBRA_DPLANE_INSTALL_SUCCESS: - dest->selected_fib = re; - for (ALL_NEXTHOPS(re->ng, nexthop)) { - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) - continue; - - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - else - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - } - zsend_route_notify_owner(re, p, ZAPI_ROUTE_INSTALLED); - break; - case ZEBRA_DPLANE_INSTALL_FAILURE: - /* - * I am not sure this is the right thing to do here - * but the code always set selected_fib before - * this assignment was moved here. - */ - dest->selected_fib = re; - - zsend_route_notify_owner(re, p, ZAPI_ROUTE_FAIL_INSTALL); - flog_err(EC_ZEBRA_DP_INSTALL_FAIL, - "%u:%s: Route install failed", re->vrf_id, - prefix2str(p, buf, sizeof(buf))); - break; - case ZEBRA_DPLANE_DELETE_SUCCESS: - /* - * The case where selected_fib is not re is - * when we have received a system route - * that is overriding our installed route - * as such we should leave the selected_fib - * pointer alone - */ - if (dest->selected_fib == re) - dest->selected_fib = NULL; - for (ALL_NEXTHOPS(re->ng, nexthop)) - UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); - - zsend_route_notify_owner(re, p, ZAPI_ROUTE_REMOVED); - break; - case ZEBRA_DPLANE_DELETE_FAILURE: - /* - * Should we set this to NULL if the - * delete fails? - */ - dest->selected_fib = NULL; - flog_err(EC_ZEBRA_DP_DELETE_FAIL, - "%u:%s: Route Deletion failure", re->vrf_id, - prefix2str(p, buf, sizeof(buf))); - - zsend_route_notify_owner(re, p, ZAPI_ROUTE_REMOVE_FAIL); - break; - case ZEBRA_DPLANE_STATUS_NONE: - break; - } -} - /* Update flag indicates whether this is a "replace" or not. Currently, this * is only used for IPv4. */ @@ -1135,8 +1101,11 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, { struct nexthop *nexthop; rib_table_info_t *info = srcdest_rnode_table_info(rn); - const struct prefix *p, *src_p; struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); + const struct prefix *p, *src_p; + enum zebra_dplane_result ret; + + rib_dest_t *dest = rib_dest_from_rnode(rn); srcdest_rnode_prefixes(rn, &p, &src_p); @@ -1168,24 +1137,39 @@ void rib_install_kernel(struct route_node *rn, struct route_entry *re, if (old && (old != re) && (old->type != re->type)) zsend_route_notify_owner(old, p, ZAPI_ROUTE_BETTER_ADMIN_WON); + /* Update fib selection */ + dest->selected_fib = re; + /* * Make sure we update the FPM any time we send new information to * the kernel. */ hook_call(rib_update, rn, "installing in kernel"); - switch (kernel_route_rib(rn, p, src_p, old, re)) { + + /* Send add or update */ + if (old && (old != re)) + ret = dplane_route_update(rn, re, old); + else + ret = dplane_route_add(rn, re); + + switch (ret) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current known DataPlane interfaces can return this, please fix"); + if (zvrf) + zvrf->installs_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: - flog_err( - EC_ZEBRA_DP_INSTALL_FAIL, - "No current known Rib Install Failure cases, please fix"); + { + char str[SRCDEST2STR_BUFFER]; + + srcdest_rnode2str(rn, str, sizeof(str)); + flog_err(EC_ZEBRA_DP_INSTALL_FAIL, + "%u:%s: Failed to enqueue dataplane install", + re->vrf_id, str); break; + } case ZEBRA_DPLANE_REQUEST_SUCCESS: - zvrf->installs++; + if (zvrf) + zvrf->installs++; break; } @@ -1197,11 +1181,8 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) { struct nexthop *nexthop; rib_table_info_t *info = srcdest_rnode_table_info(rn); - const struct prefix *p, *src_p; struct zebra_vrf *zvrf = vrf_info_lookup(re->vrf_id); - srcdest_rnode_prefixes(rn, &p, &src_p); - if (info->safi != SAFI_UNICAST) { for (ALL_NEXTHOPS(re->ng, nexthop)) UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); @@ -1210,20 +1191,25 @@ void rib_uninstall_kernel(struct route_node *rn, struct route_entry *re) /* * Make sure we update the FPM any time we send new information to - * the kernel. + * the dataplane. */ hook_call(rib_update, rn, "uninstalling from kernel"); - switch (kernel_route_rib(rn, p, src_p, re, NULL)) { + + switch (dplane_route_delete(rn, re)) { case ZEBRA_DPLANE_REQUEST_QUEUED: - flog_err( - EC_ZEBRA_DP_INVALID_RC, - "No current known DataPlane interfaces can return this, please fix"); + if (zvrf) + zvrf->removals_queued++; break; case ZEBRA_DPLANE_REQUEST_FAILURE: - flog_err( - EC_ZEBRA_DP_INSTALL_FAIL, - "No current known RIB Install Failure cases, please fix"); + { + char str[SRCDEST2STR_BUFFER]; + + srcdest_rnode2str(rn, str, sizeof(str)); + flog_err(EC_ZEBRA_DP_INSTALL_FAIL, + "%u:%s: Failed to enqueue dataplane uninstall", + re->vrf_id, str); break; + } case ZEBRA_DPLANE_REQUEST_SUCCESS: if (zvrf) zvrf->removals++; @@ -1238,17 +1224,23 @@ static void rib_uninstall(struct route_node *rn, struct route_entry *re) { rib_table_info_t *info = srcdest_rnode_table_info(rn); rib_dest_t *dest = rib_dest_from_rnode(rn); + struct nexthop *nexthop; if (dest && dest->selected_fib == re) { if (info->safi == SAFI_UNICAST) hook_call(rib_update, rn, "rib_uninstall"); - if (!RIB_SYSTEM_ROUTE(re)) - rib_uninstall_kernel(rn, re); - /* If labeled-unicast route, uninstall transit LSP. */ if (zebra_rib_labeled_unicast(re)) zebra_mpls_lsp_uninstall(info->zvrf, rn, re); + + if (!RIB_SYSTEM_ROUTE(re)) + rib_uninstall_kernel(rn, re); + + dest->selected_fib = NULL; + + for (ALL_NEXTHOPS(re->ng, nexthop)) + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); } if (CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) { @@ -1386,8 +1378,15 @@ static void rib_process_del_fib(struct zebra_vrf *zvrf, struct route_node *rn, } /* Update nexthop for route, reset changed flag. */ - nexthop_active_update(rn, old, 1); - UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); + /* Note: this code also handles the Linux case when an interface goes + * down, causing the kernel to delete routes without sending DELROUTE + * notifications + */ + if (!nexthop_active_update(rn, old, 1) && + (RIB_KERNEL_ROUTE(old))) + SET_FLAG(old->status, ROUTE_ENTRY_REMOVED); + else + UNSET_FLAG(old->status, ROUTE_ENTRY_CHANGED); } static void rib_process_update_fib(struct zebra_vrf *zvrf, @@ -1770,28 +1769,26 @@ static void rib_process(struct route_node *rn) else if (old_fib) rib_process_del_fib(zvrf, rn, old_fib); - /* Redistribute SELECTED entry */ + /* Update SELECTED entry */ if (old_selected != new_selected || selected_changed) { - struct nexthop *nexthop = NULL; - - /* Check if we have a FIB route for the destination, otherwise, - * don't redistribute it */ - if (new_fib) { - for (ALL_NEXTHOPS(new_fib->ng, nexthop)) { - if (CHECK_FLAG(nexthop->flags, - NEXTHOP_FLAG_FIB)) { - break; - } - } - } - if (!nexthop) - new_selected = NULL; if (new_selected && new_selected != new_fib) { nexthop_active_update(rn, new_selected, 1); UNSET_FLAG(new_selected->status, ROUTE_ENTRY_CHANGED); } + if (new_selected) { + SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); + + /* Special case: new route is system route, so + * dataplane update will not be done - ensure we + * redistribute the route. + */ + if (RIB_SYSTEM_ROUTE(new_selected)) + redistribute_update(p, src_p, new_selected, + old_selected); + } + if (old_selected) { if (!new_selected) redistribute_delete(p, src_p, old_selected); @@ -1799,14 +1796,6 @@ static void rib_process(struct route_node *rn) UNSET_FLAG(old_selected->flags, ZEBRA_FLAG_SELECTED); } - - if (new_selected) { - /* Install new or replace existing redistributed entry - */ - SET_FLAG(new_selected->flags, ZEBRA_FLAG_SELECTED); - redistribute_update(p, src_p, new_selected, - old_selected); - } } /* Remove all RE entries queued for removal */ @@ -1826,6 +1815,271 @@ static void rib_process(struct route_node *rn) rib_gc_dest(rn); } +/* + * Utility to match route with dplane context data + */ +static bool rib_route_match_ctx(const struct route_entry *re, + const struct zebra_dplane_ctx *ctx, + bool is_update) +{ + bool result = false; + + if (is_update) { + /* + * In 'update' case, we test info about the 'previous' or + * 'old' route + */ + if ((re->type == dplane_ctx_get_old_type(ctx)) && + (re->instance == dplane_ctx_get_old_instance(ctx))) { + result = true; + + /* TODO -- we're using this extra test, but it's not + * exactly clear why. + */ + if (re->type == ZEBRA_ROUTE_STATIC && + (re->distance != dplane_ctx_get_old_distance(ctx) || + re->tag != dplane_ctx_get_old_tag(ctx))) { + result = false; + } + } + + } else { + /* + * Ordinary, single-route case using primary context info + */ + if ((dplane_ctx_get_op(ctx) != DPLANE_OP_ROUTE_DELETE) && + CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) { + /* Skip route that's been deleted */ + goto done; + } + + if ((re->type == dplane_ctx_get_type(ctx)) && + (re->instance == dplane_ctx_get_instance(ctx))) { + result = true; + + /* TODO -- we're using this extra test, but it's not + * exactly clear why. + */ + if (re->type == ZEBRA_ROUTE_STATIC && + (re->distance != dplane_ctx_get_distance(ctx) || + re->tag != dplane_ctx_get_tag(ctx))) { + result = false; + } + } + } + +done: + + return (result); +} + +/* + * Route-update results processing after async dataplane update. + */ +static void rib_process_after(struct zebra_dplane_ctx *ctx) +{ + struct route_table *table = NULL; + struct zebra_vrf *zvrf = NULL; + struct route_node *rn = NULL; + struct route_entry *re = NULL, *old_re = NULL, *rib; + bool is_update = false; + struct nexthop *nexthop, *ctx_nexthop; + char dest_str[PREFIX_STRLEN] = ""; + enum dplane_op_e op; + enum zebra_dplane_result status; + const struct prefix *dest_pfx, *src_pfx; + + /* Locate rn and re(s) from ctx */ + + table = zebra_vrf_table_with_table_id(dplane_ctx_get_afi(ctx), + dplane_ctx_get_safi(ctx), + dplane_ctx_get_vrf(ctx), + dplane_ctx_get_table(ctx)); + if (table == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) { + zlog_debug("Failed to process dplane results: no table for afi %d, safi %d, vrf %u", + dplane_ctx_get_afi(ctx), + dplane_ctx_get_safi(ctx), + dplane_ctx_get_vrf(ctx)); + } + goto done; + } + + zvrf = vrf_info_lookup(dplane_ctx_get_vrf(ctx)); + + dest_pfx = dplane_ctx_get_dest(ctx); + + /* Note well: only capturing the prefix string if debug is enabled here; + * unconditional log messages will have to generate the string. + */ + if (IS_ZEBRA_DEBUG_DPLANE) + prefix2str(dest_pfx, dest_str, sizeof(dest_str)); + + src_pfx = dplane_ctx_get_src(ctx); + rn = srcdest_rnode_get(table, dplane_ctx_get_dest(ctx), + src_pfx ? (struct prefix_ipv6 *)src_pfx : NULL); + if (rn == NULL) { + if (IS_ZEBRA_DEBUG_DPLANE) { + zlog_debug("Failed to process dplane results: no route for %u:%s", + dplane_ctx_get_vrf(ctx), dest_str); + } + goto done; + } + + srcdest_rnode_prefixes(rn, &dest_pfx, &src_pfx); + + op = dplane_ctx_get_op(ctx); + status = dplane_ctx_get_status(ctx); + + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + zlog_debug("%u:%s Processing dplane ctx %p, op %s result %s", + dplane_ctx_get_vrf(ctx), dest_str, ctx, + dplane_op2str(op), dplane_res2str(status)); + } + + if (op == DPLANE_OP_ROUTE_DELETE) { + /* + * In the delete case, the zebra core datastructs were + * updated (or removed) at the time the delete was issued, + * so we're just notifying the route owner. + */ + if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { + zsend_route_notify_owner_ctx(ctx, ZAPI_ROUTE_REMOVED); + + if (zvrf) + zvrf->removals++; + } else { + zsend_route_notify_owner_ctx(ctx, + ZAPI_ROUTE_FAIL_INSTALL); + + zlog_warn("%u:%s: Route Deletion failure", + dplane_ctx_get_vrf(ctx), + prefix2str(dest_pfx, + dest_str, sizeof(dest_str))); + } + + /* Nothing more to do in delete case */ + goto done; + } + + /* + * Update is a bit of a special case, where we may have both old and new + * routes to post-process. + */ + is_update = dplane_ctx_is_update(ctx); + + /* + * Take a pass through the routes, look for matches with the context + * info. + */ + RNODE_FOREACH_RE(rn, rib) { + + if (re == NULL) { + if (rib_route_match_ctx(rib, ctx, false)) + re = rib; + } + + /* Check for old route match */ + if (is_update && (old_re == NULL)) { + if (rib_route_match_ctx(rib, ctx, true /*is_update*/)) + old_re = rib; + } + + /* Have we found the routes we need to work on? */ + if (re && ((!is_update || old_re))) + break; + } + + /* + * Check sequence number(s) to detect stale results before continuing + */ + if (re && (re->dplane_sequence != dplane_ctx_get_seq(ctx))) { + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + zlog_debug("%u:%s Stale dplane result for re %p", + dplane_ctx_get_vrf(ctx), dest_str, re); + } + re = NULL; + } + + if (old_re && + (old_re->dplane_sequence != dplane_ctx_get_old_seq(ctx))) { + if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) { + zlog_debug("%u:%s Stale dplane result for old_re %p", + dplane_ctx_get_vrf(ctx), dest_str, old_re); + } + old_re = NULL; + } + + /* + * Here's sort of a tough one: the route update result is stale. + * Is it better to use the context block info to generate + * redist and owner notification, or is it better to wait + * for the up-to-date result to arrive? + */ + if (re == NULL) { + /* TODO -- for now, only expose up-to-date results */ + goto done; + } + + if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) { + /* Update zebra nexthop FIB flag for each + * nexthop that was installed. + */ + for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), ctx_nexthop)) { + + for (ALL_NEXTHOPS(re->ng, nexthop)) { + if (nexthop_same(ctx_nexthop, nexthop)) + break; + } + + if (nexthop == NULL) + continue; + + if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + continue; + + if (CHECK_FLAG(ctx_nexthop->flags, + NEXTHOP_FLAG_FIB)) + SET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + else + UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB); + } + + if (zvrf) { + zvrf->installs++; + /* Set flag for nexthop tracking processing */ + zvrf->flags |= ZEBRA_VRF_RIB_SCHEDULED; + } + + /* Redistribute */ + /* TODO -- still calling the redist api using the route_entries, + * and there's a corner-case here: if there's no client + * for the 'new' route, a redist deleting the 'old' route + * will be sent. But if the 'old' context info was stale, + * 'old_re' will be NULL here and that delete will not be sent. + */ + redistribute_update(dest_pfx, src_pfx, re, old_re); + + /* Notify route owner */ + zsend_route_notify_owner(re, + dest_pfx, ZAPI_ROUTE_INSTALLED); + + } else { + zsend_route_notify_owner(re, dest_pfx, + ZAPI_ROUTE_FAIL_INSTALL); + + zlog_warn("%u:%s: Route install failed", + dplane_ctx_get_vrf(ctx), + prefix2str(dest_pfx, + dest_str, sizeof(dest_str))); + } + +done: + + /* Return context to dataplane module */ + dplane_ctx_fini(&ctx); +} + /* Take a list of route_node structs and return 1, if there was a record * picked from it and processed by rib_process(). Don't process more, * than one RN record; operate only in the specified sub-queue. @@ -1872,9 +2126,9 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex) } /* - * All meta queues have been processed. Trigger next-hop evaluation. + * Perform next-hop tracking processing after RIB updates. */ -static void meta_queue_process_complete(struct work_queue *dummy) +static void do_nht_processing(void) { struct vrf *vrf; struct zebra_vrf *zvrf; @@ -1889,15 +2143,17 @@ static void meta_queue_process_complete(struct work_queue *dummy) if (zvrf == NULL || !(zvrf->flags & ZEBRA_VRF_RIB_SCHEDULED)) continue; + if (IS_ZEBRA_DEBUG_RIB_DETAILED || IS_ZEBRA_DEBUG_NHT) + zlog_debug("NHT processing check for zvrf %s", + zvrf_name(zvrf)); + zvrf->flags &= ~ZEBRA_VRF_RIB_SCHEDULED; - zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, RNH_NEXTHOP_TYPE, + zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AF_INET, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET, 0, - RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, RNH_NEXTHOP_TYPE, + zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AF_INET6, 0, RNH_IMPORT_CHECK_TYPE, NULL); - zebra_evaluate_rnh(zvrf_id(zvrf), AF_INET6, 0, - RNH_IMPORT_CHECK_TYPE, NULL); } /* Schedule LSPs for processing, if needed. */ @@ -1912,6 +2168,14 @@ static void meta_queue_process_complete(struct work_queue *dummy) } } +/* + * All meta queues have been processed. Trigger next-hop evaluation. + */ +static void meta_queue_process_complete(struct work_queue *dummy) +{ + do_nht_processing(); +} + /* Dispatch the meta queue by picking, processing and unlocking the next RN from * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and * data @@ -1921,6 +2185,22 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data) { struct meta_queue *mq = data; unsigned i; + uint32_t queue_len, queue_limit; + + /* Ensure there's room for more dataplane updates */ + queue_limit = dplane_get_in_queue_limit(); + queue_len = dplane_get_in_queue_len(); + if (queue_len > queue_limit) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug("rib queue: dplane queue len %u, limit %u, retrying", + queue_len, queue_limit); + + /* Ensure that the meta-queue is actually enqueued */ + if (work_queue_empty(zebrad.ribq)) + work_queue_add(zebrad.ribq, zebrad.mq); + + return WQ_QUEUE_BLOCKED; + } for (i = 0; i < MQ_SIZE; i++) if (process_subq(mq->subq[i], i)) { @@ -2900,7 +3180,7 @@ void rib_sweep_route(void) rib_sweep_table(zvrf->table[AFI_IP6][SAFI_UNICAST]); } - zebra_ns_sweep_route(); + zebra_router_sweep_route(); } /* Remove specific by protocol routes from 'table'. */ @@ -2942,7 +3222,7 @@ unsigned long rib_score_proto(uint8_t proto, unsigned short instance) proto, instance, zvrf->table[AFI_IP6][SAFI_UNICAST]); - cnt += zebra_ns_score_proto(proto, instance); + cnt += zebra_router_score_proto(proto, instance); return cnt; } @@ -2966,16 +3246,75 @@ void rib_close_table(struct route_table *table) if (info->safi == SAFI_UNICAST) hook_call(rib_update, rn, NULL); - if (!RIB_SYSTEM_ROUTE(dest->selected_fib)) + if (!RIB_SYSTEM_ROUTE(dest->selected_fib)) { rib_uninstall_kernel(rn, dest->selected_fib); + dest->selected_fib = NULL; + } } } } +/* + * + */ +static int rib_process_dplane_results(struct thread *thread) +{ + struct zebra_dplane_ctx *ctx; + + do { + /* Take lock controlling queue of results */ + pthread_mutex_lock(&dplane_mutex); + { + /* Dequeue context block */ + dplane_ctx_dequeue(&rib_dplane_q, &ctx); + } + pthread_mutex_unlock(&dplane_mutex); + + if (ctx) + rib_process_after(ctx); + else + break; + + } while (1); + + /* Check for nexthop tracking processing after finishing with results */ + do_nht_processing(); + + return 0; +} + +/* + * Results are returned from the dataplane subsystem, in the context of + * the dataplane pthread. We enqueue the results here for processing by + * the main thread later. + */ +static int rib_dplane_results(const struct zebra_dplane_ctx *ctx) +{ + /* Take lock controlling queue of results */ + pthread_mutex_lock(&dplane_mutex); + { + /* Enqueue context block */ + dplane_ctx_enqueue_tail(&rib_dplane_q, ctx); + } + pthread_mutex_unlock(&dplane_mutex); + + /* Ensure event is signalled to zebra main thread */ + thread_add_event(zebrad.master, rib_process_dplane_results, NULL, 0, + &t_dplane); + + return 0; +} + /* Routing information base initialize. */ void rib_init(void) { rib_queue_init(&zebrad); + + /* Init dataplane, and register for results */ + pthread_mutex_init(&dplane_mutex, NULL); + TAILQ_INIT(&rib_dplane_q); + zebra_dplane_init(); + dplane_results_register(rib_dplane_results); } /* diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c index 622ed5ac05..b9d25a9d9b 100644 --- a/zebra/zebra_rnh.c +++ b/zebra/zebra_rnh.c @@ -36,6 +36,7 @@ #include "nexthop.h" #include "vrf.h" +#include "zebra/zebra_router.h" #include "zebra/rib.h" #include "zebra/rt.h" #include "zebra/zserv.h" @@ -260,13 +261,18 @@ void zebra_register_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) struct prefix nh; struct rnh *rnh; bool exists; + struct zebra_vrf *zvrf; + + zvrf = vrf_info_lookup(vrf_id); + if (!zvrf) + return; addr2hostprefix(pw->af, &pw->nexthop, &nh); rnh = zebra_add_rnh(&nh, vrf_id, RNH_NEXTHOP_TYPE, &exists); if (rnh && !listnode_lookup(rnh->zebra_pseudowire_list, pw)) { listnode_add(rnh->zebra_pseudowire_list, pw); pw->rnh = rnh; - zebra_evaluate_rnh(vrf_id, pw->af, 1, RNH_NEXTHOP_TYPE, &nh); + zebra_evaluate_rnh(zvrf, pw->af, 1, RNH_NEXTHOP_TYPE, &nh); } } @@ -289,7 +295,8 @@ void zebra_deregister_rnh_pseudowire(vrf_id_t vrf_id, struct zebra_pw *pw) /* Apply the NHT route-map for a client to the route (and nexthops) * resolving a NH. */ -static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, +static int zebra_rnh_apply_nht_rmap(int family, struct zebra_vrf *zvrf, + struct route_node *prn, struct route_entry *re, int proto) { int at_least_one = 0; @@ -302,8 +309,8 @@ static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, if (prn && re) { for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) { - ret = zebra_nht_route_map_check(rmap_family, proto, - &prn->p, re, nexthop); + ret = zebra_nht_route_map_check( + rmap_family, proto, &prn->p, zvrf, re, nexthop); if (ret != RMAP_DENYMATCH) { SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); at_least_one++; /* at least one valid NH */ @@ -320,7 +327,7 @@ static int zebra_rnh_apply_nht_rmap(int family, struct route_node *prn, * for BGP route for import. */ static struct route_entry * -zebra_rnh_resolve_import_entry(vrf_id_t vrfid, int family, +zebra_rnh_resolve_import_entry(struct zebra_vrf *zvrf, int family, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { @@ -330,7 +337,7 @@ zebra_rnh_resolve_import_entry(vrf_id_t vrfid, int family, *prn = NULL; - route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); + route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; if (!route_table) // unexpected return NULL; @@ -402,11 +409,9 @@ static void zebra_rnh_eval_import_check_entry(vrf_id_t vrfid, int family, /* * Notify clients registered for this nexthop about a change. */ -static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, - struct route_node *nrn, - struct rnh *rnh, - struct route_node *prn, - struct route_entry *re) +static void zebra_rnh_notify_protocol_clients( + struct zebra_vrf *zvrf, int family, struct route_node *nrn, + struct rnh *rnh, struct route_node *prn, struct route_entry *re) { struct listnode *node; struct zserv *client; @@ -418,11 +423,11 @@ static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); if (prn && re) { prefix2str(&prn->p, bufp, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: NH resolved over route %s", vrfid, - bufn, bufp); + zlog_debug("%u:%s: NH resolved over route %s", + zvrf->vrf->vrf_id, bufn, bufp); } else - zlog_debug("%u:%s: NH has become unresolved", vrfid, - bufn); + zlog_debug("%u:%s: NH has become unresolved", + zvrf->vrf->vrf_id, bufn); } for (ALL_LIST_ELEMENTS_RO(rnh->client_list, node, client)) { @@ -432,7 +437,7 @@ static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, * nexthop to see if it is filtered or not. */ num_resolving_nh = zebra_rnh_apply_nht_rmap( - family, prn, re, client->proto); + family, zvrf, prn, re, client->proto); if (num_resolving_nh) rnh->filtered[client->proto] = 0; else @@ -441,7 +446,7 @@ static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, if (IS_ZEBRA_DEBUG_NHT) zlog_debug( "%u:%s: Notifying client %s about NH %s", - vrfid, bufn, + zvrf->vrf->vrf_id, bufn, zebra_route_string(client->proto), num_resolving_nh ? "" @@ -451,11 +456,11 @@ static void zebra_rnh_notify_protocol_clients(vrf_id_t vrfid, int family, if (IS_ZEBRA_DEBUG_NHT) zlog_debug( "%u:%s: Notifying client %s about NH (unreachable)", - vrfid, bufn, + zvrf->vrf->vrf_id, bufn, zebra_route_string(client->proto)); } - send_client(rnh, client, RNH_NEXTHOP_TYPE, vrfid); + send_client(rnh, client, RNH_NEXTHOP_TYPE, zvrf->vrf->vrf_id); } } @@ -465,12 +470,11 @@ static void zebra_rnh_process_pbr_tables(int family, struct route_node *prn, struct route_entry *re) { - struct zebra_ns_table *znst; + struct zebra_router_table *zrt; struct route_entry *o_re; struct route_node *o_rn; struct listnode *node; struct zserv *client; - struct zebra_ns *zns; afi_t afi = AFI_IP; if (family == AF_INET6) @@ -488,13 +492,12 @@ static void zebra_rnh_process_pbr_tables(int family, if (!client) return; - zns = zebra_ns_lookup(NS_DEFAULT); - RB_FOREACH (znst, zebra_ns_table_head, &zns->ns_tables) { - if (afi != znst->afi) + RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) { + if (afi != zrt->afi) continue; - for (o_rn = route_top(znst->table); - o_rn; o_rn = srcdest_route_next(o_rn)) { + for (o_rn = route_top(zrt->table); o_rn; + o_rn = srcdest_route_next(o_rn)) { RNODE_FOREACH_RE (o_rn, o_re) { if (o_re->type == ZEBRA_ROUTE_PBR) break; @@ -514,22 +517,35 @@ static void zebra_rnh_process_pbr_tables(int family, } } +/* + * Utility to determine whether a candidate nexthop is useable. We make this + * check in a couple of places, so this is a single home for the logic we + * use. + */ +static bool rnh_nexthop_valid(const struct nexthop *nh) +{ + return ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB) + || CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) + && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)); +} + /* * Determine appropriate route (route entry) resolving a tracked * nexthop. */ static struct route_entry * -zebra_rnh_resolve_nexthop_entry(vrf_id_t vrfid, int family, +zebra_rnh_resolve_nexthop_entry(struct zebra_vrf *zvrf, int family, struct route_node *nrn, struct rnh *rnh, struct route_node **prn) { struct route_table *route_table; struct route_node *rn; struct route_entry *re; + struct nexthop *nexthop; *prn = NULL; - route_table = zebra_vrf_table(family2afi(family), SAFI_UNICAST, vrfid); + route_table = zvrf->table[family2afi(family)][SAFI_UNICAST]; if (!route_table) return NULL; @@ -558,12 +574,23 @@ zebra_rnh_resolve_nexthop_entry(vrf_id_t vrfid, int family, if (!CHECK_FLAG(re->flags, ZEBRA_FLAG_SELECTED)) continue; + /* Just being SELECTED isn't quite enough - must + * have an installed nexthop to be useful. + */ + for (nexthop = re->ng.nexthop; nexthop; + nexthop = nexthop->next) { + if (rnh_nexthop_valid(nexthop)) + break; + } + + if (nexthop == NULL) + continue; + if (CHECK_FLAG(rnh->flags, ZEBRA_NHT_CONNECTED)) { if ((re->type == ZEBRA_ROUTE_CONNECT) || (re->type == ZEBRA_ROUTE_STATIC)) break; if (re->type == ZEBRA_ROUTE_NHRP) { - struct nexthop *nexthop; for (nexthop = re->ng.nexthop; nexthop; nexthop = nexthop->next) @@ -606,8 +633,8 @@ static void zebra_rnh_process_pseudowires(vrf_id_t vrfid, struct rnh *rnh) * take appropriate action; this involves notifying any clients and/or * scheduling dependent static routes for processing. */ -static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force, - struct route_node *nrn, +static void zebra_rnh_eval_nexthop_entry(struct zebra_vrf *zvrf, int family, + int force, struct route_node *nrn, struct rnh *rnh, struct route_node *prn, struct route_entry *re) @@ -636,20 +663,20 @@ static void zebra_rnh_eval_nexthop_entry(vrf_id_t vrfid, int family, int force, * rnh->state. */ /* Notify registered protocol clients. */ - zebra_rnh_notify_protocol_clients(vrfid, family, nrn, rnh, prn, + zebra_rnh_notify_protocol_clients(zvrf, family, nrn, rnh, prn, rnh->state); - zebra_rnh_process_pbr_tables(family, nrn, rnh, prn, - rnh->state); + zebra_rnh_process_pbr_tables(family, nrn, rnh, prn, rnh->state); /* Process pseudowires attached to this nexthop */ - zebra_rnh_process_pseudowires(vrfid, rnh); + zebra_rnh_process_pseudowires(zvrf->vrf->vrf_id, rnh); } } /* Evaluate one tracked entry */ -static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, - rnh_type_t type, struct route_node *nrn) +static void zebra_rnh_evaluate_entry(struct zebra_vrf *zvrf, int family, + int force, rnh_type_t type, + struct route_node *nrn) { struct rnh *rnh; struct route_entry *re; @@ -658,18 +685,18 @@ static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, if (IS_ZEBRA_DEBUG_NHT) { prefix2str(&nrn->p, bufn, INET6_ADDRSTRLEN); - zlog_debug("%u:%s: Evaluate RNH, type %d %s", vrfid, bufn, type, - force ? "(force)" : ""); + zlog_debug("%u:%s: Evaluate RNH, type %d %s", zvrf->vrf->vrf_id, + bufn, type, force ? "(force)" : ""); } rnh = nrn->info; /* Identify route entry (RE) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(vrfid, family, nrn, rnh, + re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(vrfid, family, nrn, rnh, + re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, &prn); /* If the entry cannot be resolved and that is also the existing state, @@ -680,11 +707,11 @@ static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, /* Process based on type of entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - zebra_rnh_eval_import_check_entry(vrfid, family, force, nrn, - rnh, re); + zebra_rnh_eval_import_check_entry(zvrf->vrf->vrf_id, family, + force, nrn, rnh, re); else - zebra_rnh_eval_nexthop_entry(vrfid, family, force, nrn, rnh, - prn, re); + zebra_rnh_eval_nexthop_entry(zvrf, family, force, nrn, rnh, prn, + re); } /* @@ -696,7 +723,7 @@ static void zebra_rnh_evaluate_entry(vrf_id_t vrfid, int family, int force, * we can have a situation where one re entry * covers multiple nexthops we are interested in. */ -static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, +static void zebra_rnh_clear_nhc_flag(struct zebra_vrf *zvrf, int family, rnh_type_t type, struct route_node *nrn) { struct rnh *rnh; @@ -707,10 +734,10 @@ static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, /* Identify route entry (RIB) resolving this tracked entry. */ if (type == RNH_IMPORT_CHECK_TYPE) - re = zebra_rnh_resolve_import_entry(vrfid, family, nrn, rnh, + re = zebra_rnh_resolve_import_entry(zvrf, family, nrn, rnh, &prn); else - re = zebra_rnh_resolve_nexthop_entry(vrfid, family, nrn, rnh, + re = zebra_rnh_resolve_nexthop_entry(zvrf, family, nrn, rnh, &prn); if (re) { @@ -722,13 +749,13 @@ static void zebra_rnh_clear_nhc_flag(vrf_id_t vrfid, int family, /* Evaluate all tracked entries (nexthops or routes for import into BGP) * of a particular VRF and address-family or a specific prefix. */ -void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, - struct prefix *p) +void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, + rnh_type_t type, struct prefix *p) { struct route_table *rnh_table; struct route_node *nrn; - rnh_table = get_rnh_table(vrfid, family, type); + rnh_table = get_rnh_table(zvrf->vrf->vrf_id, family, type); if (!rnh_table) // unexpected return; @@ -736,7 +763,7 @@ void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, /* Evaluating a specific entry, make sure it exists. */ nrn = route_node_lookup(rnh_table, p); if (nrn && nrn->info) - zebra_rnh_evaluate_entry(vrfid, family, force, type, + zebra_rnh_evaluate_entry(zvrf, family, force, type, nrn); if (nrn) @@ -746,14 +773,14 @@ void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, rnh_type_t type, nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_evaluate_entry(vrfid, family, force, + zebra_rnh_evaluate_entry(zvrf, family, force, type, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } nrn = route_top(rnh_table); while (nrn) { if (nrn->info) - zebra_rnh_clear_nhc_flag(vrfid, family, type, + zebra_rnh_clear_nhc_flag(zvrf, family, type, nrn); nrn = route_next(nrn); /* this will also unlock nrn */ } @@ -885,9 +912,7 @@ static int send_client(struct rnh *rnh, struct zserv *client, rnh_type_t type, nump = stream_get_endp(s); stream_putc(s, 0); for (nh = re->ng.nexthop; nh; nh = nh->next) - if ((CHECK_FLAG(nh->flags, NEXTHOP_FLAG_FIB) - || CHECK_FLAG(nh->flags, NEXTHOP_FLAG_RECURSIVE)) - && CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ACTIVE)) { + if (rnh_nexthop_valid(nh)) { stream_putc(s, nh->type); switch (nh->type) { case NEXTHOP_TYPE_IPV4: diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h index f4b4b56390..33302f0ee2 100644 --- a/zebra/zebra_rnh.h +++ b/zebra/zebra_rnh.h @@ -79,7 +79,7 @@ extern void zebra_register_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_deregister_rnh_pseudowire(vrf_id_t, struct zebra_pw *); extern void zebra_remove_rnh_client(struct rnh *rnh, struct zserv *client, rnh_type_t type); -extern void zebra_evaluate_rnh(vrf_id_t vrfid, int family, int force, +extern void zebra_evaluate_rnh(struct zebra_vrf *zvrf, int family, int force, rnh_type_t type, struct prefix *p); extern void zebra_print_rnh_table(vrf_id_t vrfid, int family, struct vty *vty, rnh_type_t); diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 7a6bc6684d..bacef49836 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -39,11 +39,12 @@ #include "zebra/zebra_rnh.h" #include "zebra/zebra_routemap.h" +#ifndef VTYSH_EXTRACT_PL +#include "zebra/zebra_routemap_clippy.c" +#endif + static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER; static struct thread *zebra_t_rmap_update = NULL; -char *proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ -/* NH Tracking route map */ -char *nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; /* "any" == ZEBRA_ROUTE_MAX */ char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX]; struct nh_rmap_obj { @@ -199,11 +200,223 @@ static void route_match_interface_free(void *rule) XFREE(MTYPE_ROUTE_MAP_COMPILED, rule); } +static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf, + int af_type) +{ + int i; + + vty_out(vty, "Protocol : route-map\n"); + vty_out(vty, "------------------------\n"); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (PROTO_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + PROTO_RM_NAME(zvrf, af_type, i)); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + + if (PROTO_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-10s : %-10s\n", "any", + PROTO_RM_NAME(zvrf, af_type, i)); + else + vty_out(vty, "%-10s : none\n", "any"); +} + +static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf, + int af_type) +{ + int i; + + vty_out(vty, "Protocol : route-map\n"); + vty_out(vty, "------------------------\n"); + + for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { + if (NHT_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), + NHT_RM_NAME(zvrf, af_type, i)); + else + vty_out(vty, "%-10s : none\n", zebra_route_string(i)); + } + + if (NHT_RM_NAME(zvrf, af_type, i)) + vty_out(vty, "%-10s : %-10s\n", "any", + NHT_RM_NAME(zvrf, af_type, i)); + else + vty_out(vty, "%-10s : none\n", "any"); +} + +static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all, + const char *vrf_name) +{ + struct zebra_vrf *zvrf; + + if (vrf_all) { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = (struct zebra_vrf *)vrf->info; + if (zvrf == NULL) + continue; + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_proto_rm(vty, zvrf, af_type); + } + } else { + vrf_id_t vrf_id = VRF_DEFAULT; + + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name, false); + + zvrf = zebra_vrf_lookup_by_id(vrf_id); + if (!zvrf) + return CMD_SUCCESS; + + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_proto_rm(vty, zvrf, af_type); + } + + return CMD_SUCCESS; +} + +static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all, + const char *vrf_name) +{ + struct zebra_vrf *zvrf; + + if (vrf_all) { + struct vrf *vrf; + + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = (struct zebra_vrf *)vrf->info; + if (zvrf == NULL) + continue; + + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_nht_rm(vty, zvrf, af_type); + } + } else { + vrf_id_t vrf_id = VRF_DEFAULT; + + if (vrf_name) + VRF_GET_ID(vrf_id, vrf_name, false); + + zvrf = zebra_vrf_lookup_by_id(vrf_id); + if (!zvrf) + return CMD_SUCCESS; + + vty_out(vty, "VRF: %s\n", zvrf->vrf->name); + show_vrf_nht_rm(vty, zvrf, af_type); + } + + return CMD_SUCCESS; +} + /* Route map commands for interface matching */ struct route_map_rule_cmd route_match_interface_cmd = { "interface", route_match_interface, route_match_interface_compile, route_match_interface_free}; +static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap, + int rtype, afi_t afi, safi_t safi) +{ + struct route_table *table; + + if (PROTO_RM_NAME(zvrf, afi, rtype)) { + if (strcmp(PROTO_RM_NAME(zvrf, afi, rtype), rmap) == 0) + return CMD_SUCCESS; + + XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype)); + } + + PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + PROTO_RM_MAP(zvrf, afi, rtype) = + route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype)); + + if (PROTO_RM_MAP(zvrf, afi, rtype)) { + + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap config for protocol %d scheduling RIB processing", + zvrf->vrf->vrf_id, rtype); + /* Process routes of interested address-families. */ + table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id); + if (table) + rib_update_table(table, RIB_UPDATE_RMAP_CHANGE); + } + + return CMD_SUCCESS; +} + +static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap, + int rtype, afi_t afi, safi_t safi) +{ + struct route_table *table; + + if (!PROTO_RM_NAME(zvrf, afi, rtype)) + return CMD_SUCCESS; + + if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) { + if (PROTO_RM_MAP(zvrf, afi, rtype)) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing", + zvrf->vrf->vrf_id, rtype); + PROTO_RM_MAP(zvrf, afi, rtype) = NULL; + + /* Process routes of interested address-families. */ + table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id); + if (table) + rib_update_table(table, RIB_UPDATE_RMAP_CHANGE); + } + XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype)); + } + return CMD_SUCCESS; +} + +static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype, + int afi) +{ + + if (NHT_RM_NAME(zvrf, afi, rtype)) { + if (strcmp(NHT_RM_NAME(zvrf, afi, rtype), rmap) == 0) + return CMD_SUCCESS; + + XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); + } + + NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + NHT_RM_MAP(zvrf, afi, rtype) = + route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype)); + + if (NHT_RM_MAP(zvrf, afi, rtype)) + zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + + return CMD_SUCCESS; +} + +static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype, + int afi) +{ + + if (!NHT_RM_NAME(zvrf, afi, rtype)) + return CMD_SUCCESS; + + if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) { + if (NHT_RM_MAP(zvrf, afi, rtype)) { + if (IS_ZEBRA_DEBUG_RIB_DETAILED) + zlog_debug( + "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing", + zvrf->vrf->vrf_id, rtype); + NHT_RM_MAP(zvrf, afi, rtype) = NULL; + + zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, + NULL); + } + XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype)); + } + return CMD_SUCCESS; +} + DEFUN (match_ip_address_prefix_len, match_ip_address_prefix_len_cmd, "match ip address prefix-len (0-32)", @@ -477,251 +690,194 @@ DEFUN (no_zebra_route_map_timer, return (CMD_SUCCESS); } - -DEFUN (ip_protocol, +DEFPY (ip_protocol, ip_protocol_cmd, - "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", + "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA + " $proto route-map ROUTE-MAP$rmap", IP_STR "Filter routing info exchanged between zebra and protocol\n" FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA "Specify route-map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (proto_rm[AFI_IP][i]) { - if (strcmp(proto_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; - XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - } - proto_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug( - "%u: IPv4 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + return ret; } -DEFUN (no_ip_protocol, +DEFPY (no_ip_protocol, no_ip_protocol_cmd, - "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", + "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA + " $proto [route-map ROUTE-MAP$rmap]", NO_STR IP_STR "Stop filtering routing info between zebra and protocol\n" FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA - "Specify route map\n" + "Specify route-map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (!proto_rm[AFI_IP][i]) - return CMD_SUCCESS; + ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST); - if (!rmap || strcmp(rmap, proto_rm[AFI_IP][i]) == 0) { - XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP][i]); - proto_rm[AFI_IP][i] = NULL; - - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug( - "%u: IPv4 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + return ret; } -DEFUN (show_ip_protocol, +DEFPY (show_ip_protocol, show_ip_protocol_cmd, - "show ip protocol", - SHOW_STR - IP_STR - "IP protocol filtering status\n") + "show ip protocol [vrf ]", + SHOW_STR + IP_STR + "IP protocol filtering status\n" + VRF_FULL_CMD_HELP_STR) { - int i; + int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name); - vty_out(vty, "Protocol : route-map \n"); - vty_out(vty, "------------------------\n"); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (proto_rm[AFI_IP][i]) - vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), - proto_rm[AFI_IP][i]); - else - vty_out(vty, "%-10s : none\n", zebra_route_string(i)); - } - if (proto_rm[AFI_IP][i]) - vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP][i]); - else - vty_out(vty, "%-10s : none\n", "any"); - - return CMD_SUCCESS; + return ret; } -DEFUN (ipv6_protocol, +DEFPY (ipv6_protocol, ipv6_protocol_cmd, - "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", + "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA + " $proto route-map ROUTE-MAP$rmap", IP6_STR "Filter IPv6 routing info exchanged between zebra and protocol\n" FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA - "Specify route map\n" + "Specify route-map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (proto_rm[AFI_IP6][i]) { - if (strcmp(proto_rm[AFI_IP6][i], rmap) == 0) - return CMD_SUCCESS; - XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - } - proto_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); + ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug( - "%u: IPv6 Routemap config for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - return CMD_SUCCESS; + return ret; } -DEFUN (no_ipv6_protocol, +DEFPY (no_ipv6_protocol, no_ipv6_protocol_cmd, - "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", + "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA + " $proto [route-map ROUTE-MAP$rmap]", NO_STR IP6_STR "Stop filtering IPv6 routing info between zebra and protocol\n" FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA - "Specify route map\n" + "Specify route-map\n" "Route map name\n") { - const char *proto = argv[3]->text; - const char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (!proto_rm[AFI_IP6][i]) - return CMD_SUCCESS; - if (!rmap || strcmp(rmap, proto_rm[AFI_IP6][i]) == 0) { - XFREE(MTYPE_ROUTE_MAP_NAME, proto_rm[AFI_IP6][i]); - proto_rm[AFI_IP6][i] = NULL; + ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST); - if (IS_ZEBRA_DEBUG_RIB_DETAILED) - zlog_debug( - "%u: IPv6 Routemap unconfig for protocol %s, scheduling RIB processing", - VRF_DEFAULT, proto); - - rib_update(VRF_DEFAULT, RIB_UPDATE_RMAP_CHANGE); - } - return CMD_SUCCESS; + return ret; } -DEFUN (show_ipv6_protocol, +DEFPY (show_ipv6_protocol, show_ipv6_protocol_cmd, - "show ipv6 protocol", - SHOW_STR - IP6_STR - "IPv6 protocol filtering status\n") + "show ipv6 protocol [vrf ]", + SHOW_STR + IP6_STR + "IPv6 protocol filtering status\n" + VRF_FULL_CMD_HELP_STR) { - int i; + int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name); - vty_out(vty, "Protocol : route-map \n"); - vty_out(vty, "------------------------\n"); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (proto_rm[AFI_IP6][i]) - vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), - proto_rm[AFI_IP6][i]); - else - vty_out(vty, "%-10s : none\n", zebra_route_string(i)); - } - if (proto_rm[AFI_IP6][i]) - vty_out(vty, "%-10s : %-10s\n", "any", proto_rm[AFI_IP6][i]); - else - vty_out(vty, "%-10s : none\n", "any"); - - return CMD_SUCCESS; + return ret; } -DEFUN (ip_protocol_nht_rmap, +DEFPY (ip_protocol_nht_rmap, ip_protocol_nht_rmap_cmd, - "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", + "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA + " $proto route-map ROUTE-MAP$rmap", IP_STR "Filter Next Hop tracking route resolution\n" FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA "Specify route map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; + + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (nht_rm[AFI_IP][i]) { - if (strcmp(nht_rm[AFI_IP][i], rmap) == 0) - return CMD_SUCCESS; - XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - } + ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP); - nht_rm[AFI_IP][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - - return CMD_SUCCESS; + return ret; } -DEFUN (no_ip_protocol_nht_rmap, +DEFPY (no_ip_protocol_nht_rmap, no_ip_protocol_nht_rmap_cmd, - "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", + "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA + " $proto route-map [ROUTE-MAP$rmap]", NO_STR IP_STR "Filter Next Hop tracking route resolution\n" @@ -729,89 +885,76 @@ DEFUN (no_ip_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - int idx = 0; - char *proto = argv[3]->text; - char *rmap = argv_find(argv, argc, "ROUTE-MAP", &idx) ? argv[idx]->arg - : NULL; + int ret, rtype; - int i = strmatch(proto, "any") ? ZEBRA_ROUTE_MAX - : proto_name2num(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); - if (i < 0) { + if (!zvrf) + return CMD_WARNING; + + if (strcasecmp(proto, "any") == 0) + rtype = ZEBRA_ROUTE_MAX; + else + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (!nht_rm[AFI_IP][i]) - return CMD_SUCCESS; + ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP); - if (!rmap || strcmp(rmap, nht_rm[AFI_IP][i]) == 0) { - XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP][i]); - nht_rm[AFI_IP][i] = NULL; - zebra_evaluate_rnh(0, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); - } - return CMD_SUCCESS; + return ret; } -DEFUN (show_ip_protocol_nht, +DEFPY (show_ip_protocol_nht, show_ip_protocol_nht_cmd, - "show ip nht route-map", + "show ip nht route-map [vrf ]", SHOW_STR IP_STR "IP nexthop tracking table\n" - "IP Next Hop tracking filtering status\n") + "IP Next Hop tracking filtering status\n" + VRF_FULL_CMD_HELP_STR) { - int i; + int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name); - vty_out(vty, "Protocol : route-map \n"); - vty_out(vty, "------------------------\n"); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (nht_rm[AFI_IP][i]) - vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), - nht_rm[AFI_IP][i]); - else - vty_out(vty, "%-10s : none\n", zebra_route_string(i)); - } - if (nht_rm[AFI_IP][i]) - vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP][i]); - else - vty_out(vty, "%-10s : none\n", "any"); - - return CMD_SUCCESS; + return ret; } -DEFUN (ipv6_protocol_nht_rmap, +DEFPY (ipv6_protocol_nht_rmap, ipv6_protocol_nht_rmap_cmd, - "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " route-map ROUTE-MAP", + "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA + " $proto route-map ROUTE-MAP$rmap", IP6_STR "Filter Next Hop tracking route resolution\n" FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA "Specify route map\n" "Route map name\n") { - char *proto = argv[2]->text; - char *rmap = argv[4]->arg; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (nht_rm[AFI_IP6][i]) - XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap); - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - return CMD_SUCCESS; + ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6); + + return ret; } -DEFUN (no_ipv6_protocol_nht_rmap, +DEFPY (no_ipv6_protocol_nht_rmap, no_ipv6_protocol_nht_rmap_cmd, - "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA " [route-map ROUTE-MAP]", + "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA + " $proto [route-map ROUTE-MAP$rmap]", NO_STR IP6_STR "Filter Next Hop tracking route resolution\n" @@ -819,59 +962,39 @@ DEFUN (no_ipv6_protocol_nht_rmap, "Specify route map\n" "Route map name\n") { - char *proto = argv[3]->text; - char *rmap = (argc == 6) ? argv[5]->arg : NULL; - int i; + int ret, rtype; + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; if (strcasecmp(proto, "any") == 0) - i = ZEBRA_ROUTE_MAX; + rtype = ZEBRA_ROUTE_MAX; else - i = proto_name2num(proto); - if (i < 0) { + rtype = proto_name2num(proto); + if (rtype < 0) { vty_out(vty, "invalid protocol name \"%s\"\n", proto); return CMD_WARNING_CONFIG_FAILED; } - if (nht_rm[AFI_IP6][i] && rmap && strcmp(rmap, nht_rm[AFI_IP6][i])) { - vty_out(vty, "invalid route-map \"%s\"\n", rmap); - return CMD_WARNING_CONFIG_FAILED; - } + ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6); - if (nht_rm[AFI_IP6][i]) { - XFREE(MTYPE_ROUTE_MAP_NAME, nht_rm[AFI_IP6][i]); - nht_rm[AFI_IP6][i] = NULL; - } - - zebra_evaluate_rnh(0, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); - - return CMD_SUCCESS; + return ret; } -DEFUN (show_ipv6_protocol_nht, +DEFPY (show_ipv6_protocol_nht, show_ipv6_protocol_nht_cmd, - "show ipv6 nht route-map", + "show ipv6 nht route-map [vrf ]", SHOW_STR IP6_STR "Next Hop filtering status\n" - "Route-map\n") + "Route-map\n" + VRF_FULL_CMD_HELP_STR) { - int i; + int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name); - vty_out(vty, "Protocol : route-map \n"); - vty_out(vty, "------------------------\n"); - for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (nht_rm[AFI_IP6][i]) - vty_out(vty, "%-10s : %-10s\n", zebra_route_string(i), - nht_rm[AFI_IP6][i]); - else - vty_out(vty, "%-10s : none\n", zebra_route_string(i)); - } - if (nht_rm[AFI_IP][i]) - vty_out(vty, "%-10s : %-10s\n", "any", nht_rm[AFI_IP6][i]); - else - vty_out(vty, "%-10s : none\n", "any"); - - return CMD_SUCCESS; + return ret; } /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/ @@ -1309,42 +1432,63 @@ static void zebra_rib_table_rm_update(const char *rmap) { int i = 0; struct route_table *table; + struct vrf *vrf = NULL; + struct zebra_vrf *zvrf = NULL; char *rmap_name; char afi_ip = 0; char afi_ipv6 = 0; - for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { - /* Check for ip routemap table */ - rmap_name = proto_rm[AFI_IP][i]; - if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s : AFI_IP rmap %s, route type %s", - __func__, rmap, zebra_route_string(i)); - /* There is single rib table for all protocols */ - if (afi_ip == 0) { - table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, - VRF_DEFAULT); - if (table) { - afi_ip = 1; - rib_update_table(table, - RIB_UPDATE_RMAP_CHANGE); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = vrf->info; + if (!zvrf) + continue; + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i); + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s : AFI_IP rmap %s, route type %s", + __func__, rmap, + zebra_route_string(i)); + + PROTO_RM_MAP(zvrf, AFI_IP, i) = + route_map_lookup_by_name(rmap_name); + /* There is single rib table for all protocols + */ + if (afi_ip == 0) { + table = zvrf->table[AFI_IP] + [SAFI_UNICAST]; + if (table) { + + afi_ip = 1; + rib_update_table( + table, + RIB_UPDATE_RMAP_CHANGE); + } } } - } + rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i); + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s : AFI_IP6 rmap %s, route type %s", + __func__, rmap, + zebra_route_string(i)); - /* Check for ipv6 routemap table */ - rmap_name = proto_rm[AFI_IP6][i]; - if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s : AFI_IP6 rmap %s,route type %s", - __func__, rmap, zebra_route_string(i)); - if (afi_ipv6 == 0) { - table = zebra_vrf_table(AFI_IP6, SAFI_UNICAST, - VRF_DEFAULT); - if (table) { - afi_ipv6 = 1; - rib_update_table(table, - RIB_UPDATE_RMAP_CHANGE); + PROTO_RM_MAP(zvrf, AFI_IP6, i) = + route_map_lookup_by_name(rmap_name); + /* There is single rib table for all protocols + */ + if (afi_ipv6 == 0) { + table = zvrf->table[AFI_IP6] + [SAFI_UNICAST]; + if (table) { + + afi_ipv6 = 1; + rib_update_table( + table, + RIB_UPDATE_RMAP_CHANGE); + } } } } @@ -1358,31 +1502,68 @@ static void zebra_rib_table_rm_update(const char *rmap) static void zebra_nht_rm_update(const char *rmap) { int i = 0; + struct route_table *table; + struct vrf *vrf = NULL; + struct zebra_vrf *zvrf = NULL; char *rmap_name; char afi_ip = 0; char afi_ipv6 = 0; - for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { - rmap_name = nht_rm[AFI_IP][i]; - if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s : AFI_IP rmap %s route type %s", - __func__, rmap, zebra_route_string(i)); - if (afi_ip == 0) { - afi_ip = 1; - zebra_evaluate_rnh(0, AF_INET, 1, - RNH_NEXTHOP_TYPE, NULL); + RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) { + zvrf = vrf->info; + if (!zvrf) + continue; + for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) { + rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i); + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s : AFI_IP rmap %s, route type %s", + __func__, rmap, + zebra_route_string(i)); + + NHT_RM_MAP(zvrf, AFI_IP, i) = + route_map_lookup_by_name(rmap_name); + /* There is single rib table for all protocols + */ + if (afi_ip == 0) { + table = zvrf->table[AFI_IP] + [SAFI_UNICAST]; + if (table) { + + afi_ip = 1; + + zebra_evaluate_rnh( + zvrf, AF_INET, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } } - } - rmap_name = nht_rm[AFI_IP6][i]; - if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { - if (IS_ZEBRA_DEBUG_EVENT) - zlog_debug("%s : AFI_IP6 rmap %s route type %s", - __func__, rmap, zebra_route_string(i)); - if (afi_ipv6 == 0) { - afi_ipv6 = 1; - zebra_evaluate_rnh(0, AF_INET6, 1, - RNH_NEXTHOP_TYPE, NULL); + + rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i); + if (rmap_name && (strcmp(rmap_name, rmap) == 0)) { + if (IS_ZEBRA_DEBUG_EVENT) + zlog_debug( + "%s : AFI_IP6 rmap %s, route type %s", + __func__, rmap, + zebra_route_string(i)); + + NHT_RM_MAP(zvrf, AFI_IP6, i) = + route_map_lookup_by_name(rmap_name); + /* There is single rib table for all protocols + */ + if (afi_ipv6 == 0) { + table = zvrf->table[AFI_IP6] + [SAFI_UNICAST]; + if (table) { + + afi_ipv6 = 1; + + zebra_evaluate_rnh( + zvrf, AF_INET, 1, + RNH_NEXTHOP_TYPE, NULL); + } + } } } } @@ -1439,28 +1620,26 @@ void zebra_route_map_write_delay_timer(struct vty *vty) return; } -route_map_result_t zebra_route_map_check(int family, int rib_type, - uint8_t instance, - const struct prefix *p, - struct nexthop *nexthop, - vrf_id_t vrf_id, route_tag_t tag) +route_map_result_t +zebra_route_map_check(int family, int rib_type, uint8_t instance, + const struct prefix *p, struct nexthop *nexthop, + struct zebra_vrf *zvrf, route_tag_t tag) { struct route_map *rmap = NULL; route_map_result_t ret = RMAP_MATCH; struct nh_rmap_obj nh_obj; nh_obj.nexthop = nexthop; - nh_obj.vrf_id = vrf_id; + nh_obj.vrf_id = nexthop->vrf_id; nh_obj.source_protocol = rib_type; nh_obj.instance = instance; nh_obj.metric = 0; nh_obj.tag = tag; if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name(proto_rm[family][rib_type]); - if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name( - proto_rm[family][ZEBRA_ROUTE_MAX]); + rmap = PROTO_RM_MAP(zvrf, family, rib_type); + if (!rmap && PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX)) + rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX); if (rmap) { ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); } @@ -1514,6 +1693,7 @@ zebra_import_table_route_map_check(int family, int re_type, uint8_t instance, route_map_result_t zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, + struct zebra_vrf *zvrf, struct route_entry *re, struct nexthop *nexthop) { @@ -1529,10 +1709,9 @@ route_map_result_t zebra_nht_route_map_check(int family, int client_proto, nh_obj.tag = re->tag; if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX) - rmap = route_map_lookup_by_name(nht_rm[family][client_proto]); - if (!rmap && nht_rm[family][ZEBRA_ROUTE_MAX]) - rmap = route_map_lookup_by_name( - nht_rm[family][ZEBRA_ROUTE_MAX]); + rmap = NHT_RM_MAP(zvrf, family, client_proto); + if (!rmap && NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX)) + rmap = NHT_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX); if (rmap) ret = route_map_apply(rmap, p, RMAP_ZEBRA, &nh_obj); @@ -1576,43 +1755,54 @@ static void zebra_route_map_event(route_map_event_t event, } /* ip protocol configuration write function */ -void zebra_routemap_config_write_protocol(struct vty *vty) +void zebra_routemap_config_write_protocol(struct vty *vty, + struct zebra_vrf *zvrf) { int i; + char space[2]; + + memset(space, 0, sizeof(space)); + + if (zvrf_id(zvrf) != VRF_DEFAULT) + sprintf(space, "%s", " "); for (i = 0; i < ZEBRA_ROUTE_MAX; i++) { - if (proto_rm[AFI_IP][i]) - vty_out(vty, "ip protocol %s route-map %s\n", - zebra_route_string(i), proto_rm[AFI_IP][i]); + if (PROTO_RM_NAME(zvrf, AFI_IP, i)) + vty_out(vty, "%sip protocol %s route-map %s\n", space, + zebra_route_string(i), + PROTO_RM_NAME(zvrf, AFI_IP, i)); - if (proto_rm[AFI_IP6][i]) - vty_out(vty, "ipv6 protocol %s route-map %s\n", - zebra_route_string(i), proto_rm[AFI_IP6][i]); + if (PROTO_RM_NAME(zvrf, AFI_IP6, i)) + vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, + zebra_route_string(i), + PROTO_RM_NAME(zvrf, AFI_IP6, i)); - if (nht_rm[AFI_IP][i]) - vty_out(vty, "ip nht %s route-map %s\n", - zebra_route_string(i), nht_rm[AFI_IP][i]); + if (NHT_RM_NAME(zvrf, AFI_IP, i)) + vty_out(vty, "%sip nht %s route-map %s\n", space, + zebra_route_string(i), + NHT_RM_NAME(zvrf, AFI_IP, i)); - if (nht_rm[AFI_IP6][i]) - vty_out(vty, "ipv6 nht %s route-map %s\n", - zebra_route_string(i), nht_rm[AFI_IP6][i]); + if (NHT_RM_NAME(zvrf, AFI_IP6, i)) + vty_out(vty, "%sipv6 nht %s route-map %s\n", space, + zebra_route_string(i), + NHT_RM_NAME(zvrf, AFI_IP6, i)); } - if (proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]) - vty_out(vty, "ip protocol %s route-map %s\n", "any", - proto_rm[AFI_IP][ZEBRA_ROUTE_MAX]); + if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX)) + vty_out(vty, "%sip protocol %s route-map %s\n", space, "any", + PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX)); - if (proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) - vty_out(vty, "ipv6 protocol %s route-map %s\n", "any", - proto_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); + if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX)) + vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any", + PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX)); - if (nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]) - vty_out(vty, "ip nht %s route-map %s\n", "any", - nht_rm[AFI_IP][ZEBRA_ROUTE_MAX]); + if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX)) + vty_out(vty, "%sip nht %s route-map %s\n", space, "any", + NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX)); - if (nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]) - vty_out(vty, "ipv6 nht %s route-map %s\n", "any", - nht_rm[AFI_IP6][ZEBRA_ROUTE_MAX]); + if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX)) + vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any", + NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX)); if (zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER) vty_out(vty, "zebra route-map delay-timer %d\n", @@ -1623,15 +1813,23 @@ void zebra_route_map_init() { install_element(CONFIG_NODE, &ip_protocol_cmd); install_element(CONFIG_NODE, &no_ip_protocol_cmd); + install_element(VRF_NODE, &ip_protocol_cmd); + install_element(VRF_NODE, &no_ip_protocol_cmd); install_element(VIEW_NODE, &show_ip_protocol_cmd); install_element(CONFIG_NODE, &ipv6_protocol_cmd); install_element(CONFIG_NODE, &no_ipv6_protocol_cmd); + install_element(VRF_NODE, &ipv6_protocol_cmd); + install_element(VRF_NODE, &no_ipv6_protocol_cmd); install_element(VIEW_NODE, &show_ipv6_protocol_cmd); install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd); install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd); + install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd); + install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd); install_element(VIEW_NODE, &show_ip_protocol_nht_cmd); install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd); install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd); + install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd); + install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd); install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd); install_element(CONFIG_NODE, &zebra_route_map_timer_cmd); install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd); diff --git a/zebra/zebra_routemap.h b/zebra/zebra_routemap.h index d33487d7af..a8579e7c6e 100644 --- a/zebra/zebra_routemap.h +++ b/zebra/zebra_routemap.h @@ -25,7 +25,8 @@ #include "lib/routemap.h" extern void zebra_route_map_init(void); -extern void zebra_routemap_config_write_protocol(struct vty *vty); +extern void zebra_routemap_config_write_protocol(struct vty *vty, + struct zebra_vrf *vrf); extern char *zebra_get_import_table_route_map(afi_t afi, uint32_t table); extern void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name, uint32_t table); @@ -36,16 +37,15 @@ extern void zebra_route_map_write_delay_timer(struct vty *); extern route_map_result_t zebra_import_table_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, - struct nexthop *nexthop, - vrf_id_t vrf_id, route_tag_t tag, - const char *rmap_name); + struct nexthop *nexthop, vrf_id_t vrf_id, + route_tag_t tag, const char *rmap_name); extern route_map_result_t zebra_route_map_check(int family, int rib_type, uint8_t instance, const struct prefix *p, struct nexthop *nexthop, - vrf_id_t vrf_id, route_tag_t tag); + struct zebra_vrf *zvrf, route_tag_t tag); extern route_map_result_t zebra_nht_route_map_check(int family, int client_proto, const struct prefix *p, - struct route_entry *, struct nexthop *nexthop); - + struct zebra_vrf *zvrf, struct route_entry *, + struct nexthop *nexthop); #endif diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c new file mode 100644 index 0000000000..99d96fd67f --- /dev/null +++ b/zebra/zebra_router.c @@ -0,0 +1,189 @@ +/* Zebra Router Code. + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of FRR. + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include "zebra.h" + +#include "zebra_router.h" +#include "zebra_memory.h" +#include "zebra_pbr.h" + +struct zebra_router zrouter; + +static inline int +zebra_router_table_entry_compare(const struct zebra_router_table *e1, + const struct zebra_router_table *e2); + +RB_GENERATE(zebra_router_table_head, zebra_router_table, + zebra_router_table_entry, zebra_router_table_entry_compare); + + +static inline int +zebra_router_table_entry_compare(const struct zebra_router_table *e1, + const struct zebra_router_table *e2) +{ + if (e1->tableid < e2->tableid) + return -1; + if (e1->tableid > e2->tableid) + return 1; + if (e1->ns_id < e2->ns_id) + return -1; + if (e1->ns_id > e2->ns_id) + return 1; + if (e1->afi < e2->afi) + return -1; + if (e1->afi > e2->afi) + return 1; + return (e1->safi - e2->safi); +} + + +struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf, + uint32_t tableid, afi_t afi, + safi_t safi) +{ + struct zebra_router_table finder; + struct zebra_router_table *zrt; + + memset(&finder, 0, sizeof(finder)); + finder.afi = afi; + finder.safi = safi; + finder.tableid = tableid; + finder.ns_id = zvrf->zns->ns_id; + zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder); + + if (zrt) + return zrt->table; + else + return NULL; +} + +struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf, + uint32_t tableid, afi_t afi, + safi_t safi) +{ + struct zebra_router_table finder; + struct zebra_router_table *zrt; + rib_table_info_t *info; + + memset(&finder, 0, sizeof(finder)); + finder.afi = afi; + finder.safi = safi; + finder.tableid = tableid; + finder.ns_id = zvrf->zns->ns_id; + zrt = RB_FIND(zebra_router_table_head, &zrouter.tables, &finder); + + if (zrt) + return zrt->table; + + zrt = XCALLOC(MTYPE_ZEBRA_NS, sizeof(*zrt)); + zrt->tableid = tableid; + zrt->afi = afi; + zrt->ns_id = zvrf->zns->ns_id; + zrt->table = + (afi == AFI_IP6) ? srcdest_table_init() : route_table_init(); + + info = XCALLOC(MTYPE_RIB_TABLE_INFO, sizeof(*info)); + info->zvrf = zvrf; + info->afi = afi; + info->safi = SAFI_UNICAST; + route_table_set_info(zrt->table, info); + zrt->table->cleanup = zebra_rtable_node_cleanup; + + RB_INSERT(zebra_router_table_head, &zrouter.tables, zrt); + return zrt->table; +} + +unsigned long zebra_router_score_proto(uint8_t proto, unsigned short instance) +{ + struct zebra_router_table *zrt; + unsigned long cnt = 0; + + RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) { + if (zrt->ns_id != NS_DEFAULT) + continue; + cnt += rib_score_proto_table(proto, instance, zrt->table); + } + return cnt; +} + +void zebra_router_sweep_route(void) +{ + struct zebra_router_table *zrt; + + RB_FOREACH (zrt, zebra_router_table_head, &zrouter.tables) { + if (zrt->ns_id != NS_DEFAULT) + continue; + rib_sweep_table(zrt->table); + } +} + +static void zebra_router_free_table(struct zebra_router_table *zrt) +{ + void *table_info; + + rib_close_table(zrt->table); + + table_info = route_table_get_info(zrt->table); + route_table_finish(zrt->table); + XFREE(MTYPE_RIB_TABLE_INFO, table_info); + XFREE(MTYPE_ZEBRA_NS, zrt); +} + +void zebra_router_terminate(void) +{ + struct zebra_router_table *zrt, *tmp; + + RB_FOREACH_SAFE (zrt, zebra_router_table_head, &zrouter.tables, tmp) { + RB_REMOVE(zebra_router_table_head, &zrouter.tables, zrt); + zebra_router_free_table(zrt); + } + + hash_clean(zrouter.rules_hash, zebra_pbr_rules_free); + hash_free(zrouter.rules_hash); + + hash_clean(zrouter.ipset_entry_hash, zebra_pbr_ipset_entry_free), + hash_clean(zrouter.ipset_hash, zebra_pbr_ipset_free); + hash_free(zrouter.ipset_hash); + hash_free(zrouter.ipset_entry_hash); + hash_clean(zrouter.iptable_hash, zebra_pbr_iptable_free); + hash_free(zrouter.iptable_hash); +} + +void zebra_router_init(void) +{ + zrouter.l3vni_table = NULL; + + zrouter.rules_hash = hash_create_size(8, zebra_pbr_rules_hash_key, + zebra_pbr_rules_hash_equal, + "Rules Hash"); + + zrouter.ipset_hash = + hash_create_size(8, zebra_pbr_ipset_hash_key, + zebra_pbr_ipset_hash_equal, "IPset Hash"); + + zrouter.ipset_entry_hash = hash_create_size( + 8, zebra_pbr_ipset_entry_hash_key, + zebra_pbr_ipset_entry_hash_equal, "IPset Hash Entry"); + + zrouter.iptable_hash = hash_create_size(8, zebra_pbr_iptable_hash_key, + zebra_pbr_iptable_hash_equal, + "IPtable Hash Entry"); +} diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h new file mode 100644 index 0000000000..d6b8b66087 --- /dev/null +++ b/zebra/zebra_router.h @@ -0,0 +1,84 @@ +/* Zebra Router header. + * Copyright (C) 2018 Cumulus Networks, Inc. + * Donald Sharp + * + * This file is part of FRR. + * + * FRR is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * FRR is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with FRR; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ +#ifndef __ZEBRA_ROUTER_H__ +#define __ZEBRA_ROUTER_H__ + +#include "zebra/zebra_ns.h" + +/* + * This header file contains the idea of a router and as such + * owns data that is associated with a router from zebra's + * perspective. + */ + +struct zebra_router_table { + RB_ENTRY(zebra_router_table) zebra_router_table_entry; + + uint32_t tableid; + afi_t afi; + safi_t safi; + ns_id_t ns_id; + + struct route_table *table; +}; +RB_HEAD(zebra_router_table_head, zebra_router_table); +RB_PROTOTYPE(zebra_router_table_head, zebra_router_table, + zebra_router_table_entry, zebra_router_table_entry_compare) + +struct zebra_router { + + struct zebra_router_table_head tables; + + /* L3-VNI hash table (for EVPN). Only in default instance */ + struct hash *l3vni_table; + + struct hash *rules_hash; + + struct hash *ipset_hash; + + struct hash *ipset_entry_hash; + + struct hash *iptable_hash; + +#if defined(HAVE_RTADV) + struct rtadv rtadv; +#endif /* HAVE_RTADV */ +}; + +extern struct zebra_router zrouter; + +extern void zebra_router_init(void); +extern void zebra_router_terminate(void); + +extern struct route_table *zebra_router_find_table(struct zebra_vrf *zvrf, + uint32_t tableid, afi_t afi, + safi_t safi); +extern struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf, + uint32_t tableid, afi_t afi, + safi_t safi); + +extern int zebra_router_config_write(struct vty *vty); + +extern unsigned long zebra_router_score_proto(uint8_t proto, + unsigned short instance); +extern void zebra_router_sweep_route(void); +#endif diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 9a0ebbaba7..e98a533609 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -28,6 +28,7 @@ #include "vrf.h" #include "vty.h" +#include "zebra/zebra_router.h" #include "zebra/debug.h" #include "zebra/zapi_msg.h" #include "zebra/rib.h" @@ -39,6 +40,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/zebra_vxlan.h" #include "zebra/zebra_netns_notify.h" +#include "zebra/zebra_routemap.h" extern struct zebra_t zebrad; @@ -143,7 +145,6 @@ static int zebra_vrf_enable(struct vrf *vrf) static int zebra_vrf_disable(struct vrf *vrf) { struct zebra_vrf *zvrf = vrf->info; - struct route_table *table; struct interface *ifp; afi_t afi; safi_t safi; @@ -201,15 +202,16 @@ static int zebra_vrf_disable(struct vrf *vrf) /* Cleanup (free) routing tables and NHT tables. */ for (afi = AFI_IP; afi <= AFI_IP6; afi++) { - void *table_info; - - for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) { - table = zvrf->table[afi][safi]; - table_info = route_table_get_info(table); - route_table_finish(table); - XFREE(MTYPE_RIB_TABLE_INFO, table_info); + /* + * Set the table pointer to NULL as that + * we no-longer need a copy of it, nor do we + * own this data, the zebra_router structure + * owns these tables. Once we've cleaned up the + * table, see rib_close_table above + * we no-longer need this pointer. + */ + for (safi = SAFI_UNICAST; safi <= SAFI_MULTICAST; safi++) zvrf->table[afi][safi] = NULL; - } route_table_finish(zvrf->rnh_table[afi]); zvrf->rnh_table[afi] = NULL; @@ -373,10 +375,8 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, assert(!zvrf->table[afi][safi]); - if (afi == AFI_IP6) - table = srcdest_table_init(); - else - table = route_table_init(); + table = zebra_router_get_table(zvrf, zvrf->table_id, afi, safi); + table->cleanup = zebra_rtable_node_cleanup; zvrf->table[afi][safi] = table; @@ -441,14 +441,11 @@ struct route_table *zebra_vrf_other_route_table(afi_t afi, uint32_t table_id, vrf_id_t vrf_id) { struct zebra_vrf *zvrf; - struct zebra_ns *zns; zvrf = vrf_info_lookup(vrf_id); if (!zvrf) return NULL; - zns = zvrf->zns; - if (afi >= AFI_MAX) return NULL; @@ -460,7 +457,8 @@ struct route_table *zebra_vrf_other_route_table(afi_t afi, uint32_t table_id, * so in all cases, it does not use specific table * so it is possible to configure tables in this VRF */ - return zebra_ns_get_table(zns, zvrf, table_id, afi); + return zebra_router_get_table(zvrf, table_id, afi, + SAFI_UNICAST); } } @@ -481,7 +479,6 @@ static int vrf_config_write(struct vty *vty) if (zvrf_id(zvrf) == VRF_DEFAULT) { if (zvrf->l3vni) vty_out(vty, "vni %u\n", zvrf->l3vni); - vty_out(vty, "!\n"); } else { vty_frame(vty, "vrf %s\n", zvrf_name(zvrf)); if (zvrf->l3vni) @@ -491,11 +488,14 @@ static int vrf_config_write(struct vty *vty) ? " prefix-routes-only" : ""); zebra_ns_config_write(vty, (struct ns *)vrf->ns_ctxt); - } + zebra_routemap_config_write_protocol(vty, zvrf); + if (zvrf_id(zvrf) != VRF_DEFAULT) vty_endframe(vty, " exit-vrf\n!\n"); + else + vty_out(vty, "!\n"); } return 0; } diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index b8664f4ec7..ef02ca63e5 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -1,7 +1,7 @@ /* * Zebra Vrf Header * Copyright (C) 2016 Cumulus Networks - * Donald Sahrp + * Donald Sharp * * This file is part of Quagga. * @@ -22,6 +22,8 @@ #if !defined(__ZEBRA_VRF_H__) #define __ZEBRA_VRF_H__ +#include "vxlan.h" + #include #include #include @@ -32,6 +34,11 @@ typedef struct mpls_srgb_t_ { uint32_t end_label; } mpls_srgb_t; +struct zebra_rmap { + char *name; + struct route_map *map; +}; + /* Routing table instance. */ struct zebra_vrf { /* Back pointer */ @@ -92,6 +99,9 @@ struct zebra_vrf { struct zebra_pw_head pseudowires; struct zebra_static_pw_head static_pseudowires; + struct zebra_rmap proto_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; + struct zebra_rmap nht_rm[AFI_MAX][ZEBRA_ROUTE_MAX + 1]; + /* MPLS processing flags */ uint16_t mpls_flags; #define MPLS_FLAG_SCHEDULE_LSPS (1 << 0) @@ -115,13 +125,31 @@ struct zebra_vrf { /* l3-vni info */ vni_t l3vni; + /* + * Flooding mechanism for BUM packets for VxLAN-EVPN. + */ + enum vxlan_flood_control vxlan_flood_ctrl; + /* Route Installs */ uint64_t installs; uint64_t removals; + uint64_t installs_queued; + uint64_t removals_queued; uint64_t neigh_updates; uint64_t lsp_installs; uint64_t lsp_removals; }; +#define PROTO_RM_NAME(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].name +#define NHT_RM_NAME(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].name +#define PROTO_RM_MAP(zvrf, afi, rtype) zvrf->proto_rm[afi][rtype].map +#define NHT_RM_MAP(zvrf, afi, rtype) zvrf->nht_rm[afi][rtype].map + +/* + * special macro to allow us to get the correct zebra_vrf + */ +#define ZEBRA_DECLVAR_CONTEXT(A, B) \ + struct vrf *A = VTY_GET_CONTEXT(vrf); \ + struct zebra_vrf *B = (A) ? A->info : vrf_info_lookup(VRF_DEFAULT) static inline vrf_id_t zvrf_id(struct zebra_vrf *zvrf) { diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c index 86792fdd89..17609a03fe 100644 --- a/zebra/zebra_vty.c +++ b/zebra/zebra_vty.c @@ -35,6 +35,7 @@ #include "srcdest_table.h" #include "vxlan.h" +#include "zebra/zebra_router.h" #include "zebra/zserv.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_mpls.h" @@ -67,13 +68,6 @@ static void vty_show_ip_route_summary(struct vty *vty, static void vty_show_ip_route_summary_prefix(struct vty *vty, struct route_table *table); -/* - * special macro to allow us to get the correct zebra_vrf - */ -#define ZEBRA_DECLVAR_CONTEXT(A, B) \ - struct vrf *A = VTY_GET_CONTEXT(vrf); \ - struct zebra_vrf *B = (vrf) ? vrf->info : NULL; - /* VNI range as per RFC 7432 */ #define CMD_VNI_RANGE "(1-16777215)" @@ -302,7 +296,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn, if (vrf) vty_out(vty, "(vrf %s)", vrf->name); else - vty_out(vty, "(vrf UKNOWN)"); + vty_out(vty, "(vrf UNKNOWN)"); } if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE)) @@ -677,7 +671,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn, if (vrf) vty_out(vty, "(vrf %s)", vrf->name); else - vty_out(vty, "(vrf UKNOWN)"); + vty_out(vty, "(vrf UNKNOWN)"); } if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)) @@ -903,7 +897,7 @@ DEFPY (show_route_table, struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); struct route_table *t; - t = zebra_ns_find_table(zvrf->zns, table, afi); + t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST); if (t) do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false, 0, 0, !!json); @@ -932,7 +926,7 @@ DEFPY (show_route_table_vrf, VRF_GET_ID(vrf_id, vrf_name, !!json); zvrf = zebra_vrf_lookup_by_id(vrf_id); - t = zebra_ns_find_table(zvrf->zns, table, afi); + t = zebra_router_find_table(zvrf, table, afi, SAFI_UNICAST); if (t) do_show_route_helper(vty, zvrf, t, afi, false, 0, false, false, 0, 0, !!json); @@ -1027,11 +1021,17 @@ DEFUN (ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + if (zebra_rnh_ip_default_route) return CMD_SUCCESS; zebra_rnh_ip_default_route = 1; - zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + + zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1043,11 +1043,16 @@ DEFUN (no_ip_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + if (!zebra_rnh_ip_default_route) return CMD_SUCCESS; zebra_rnh_ip_default_route = 0; - zebra_evaluate_rnh(VRF_DEFAULT, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AF_INET, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1058,11 +1063,16 @@ DEFUN (ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + if (zebra_rnh_ipv6_default_route) return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 1; - zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -1074,11 +1084,17 @@ DEFUN (no_ipv6_nht_default_route, "Filter Next Hop tracking route resolution\n" "Resolve via default route\n") { + + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); + + if (!zvrf) + return CMD_WARNING; + if (!zebra_rnh_ipv6_default_route) return CMD_SUCCESS; zebra_rnh_ipv6_default_route = 0; - zebra_evaluate_rnh(VRF_DEFAULT, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); + zebra_evaluate_rnh(zvrf, AF_INET6, 1, RNH_NEXTHOP_TYPE, NULL); return CMD_SUCCESS; } @@ -2359,9 +2375,6 @@ static int config_write_protocol(struct vty *vty) == MCAST_MIX_DISTANCE ? "lower-distance" : "longer-prefix"); - - zebra_routemap_config_write_protocol(vty); - return 1; } @@ -2555,6 +2568,76 @@ DEFUN (no_ipv6_forwarding, return CMD_SUCCESS; } +/* Display dataplane info */ +DEFUN (show_dataplane, + show_dataplane_cmd, + "show zebra dplane [detailed]", + SHOW_STR + ZEBRA_STR + "Zebra dataplane information\n" + "Detailed output\n") +{ + int idx = 0; + bool detailed = false; + + if (argv_find(argv, argc, "detailed", &idx)) + detailed = true; + + return dplane_show_helper(vty, detailed); +} + +/* Display dataplane providers info */ +DEFUN (show_dataplane_providers, + show_dataplane_providers_cmd, + "show zebra dplane providers [detailed]", + SHOW_STR + ZEBRA_STR + "Zebra dataplane information\n" + "Zebra dataplane provider information\n" + "Detailed output\n") +{ + int idx = 0; + bool detailed = false; + + if (argv_find(argv, argc, "detailed", &idx)) + detailed = true; + + return dplane_show_provs_helper(vty, detailed); +} + +/* Configure dataplane incoming queue limit */ +DEFUN (zebra_dplane_queue_limit, + zebra_dplane_queue_limit_cmd, + "zebra dplane limit (0-10000)", + ZEBRA_STR + "Zebra dataplane\n" + "Limit incoming queued updates\n" + "Number of queued updates\n") +{ + uint32_t limit = 0; + + limit = strtoul(argv[3]->arg, NULL, 10); + + dplane_set_in_queue_limit(limit, true); + + return CMD_SUCCESS; +} + +/* Reset dataplane queue limit to default value */ +DEFUN (no_zebra_dplane_queue_limit, + no_zebra_dplane_queue_limit_cmd, + "no zebra dplane limit [(0-10000)]", + NO_STR + ZEBRA_STR + "Zebra dataplane\n" + "Limit incoming queued updates\n" + "Number of queued updates\n") +{ + dplane_set_in_queue_limit(0, false); + + return CMD_SUCCESS; +} + /* Table configuration write function. */ static int config_write_table(struct vty *vty) { @@ -2649,6 +2732,10 @@ void zebra_vty_init(void) install_element(CONFIG_NODE, &no_ip_nht_default_route_cmd); install_element(CONFIG_NODE, &ipv6_nht_default_route_cmd); install_element(CONFIG_NODE, &no_ipv6_nht_default_route_cmd); + install_element(VRF_NODE, &ip_nht_default_route_cmd); + install_element(VRF_NODE, &no_ip_nht_default_route_cmd); + install_element(VRF_NODE, &ipv6_nht_default_route_cmd); + install_element(VRF_NODE, &no_ipv6_nht_default_route_cmd); install_element(VIEW_NODE, &show_ipv6_mroute_cmd); /* Commands for VRF */ @@ -2681,5 +2768,8 @@ void zebra_vty_init(void) install_element(VRF_NODE, &vrf_vni_mapping_cmd); install_element(VRF_NODE, &no_vrf_vni_mapping_cmd); - + install_element(VIEW_NODE, &show_dataplane_cmd); + install_element(VIEW_NODE, &show_dataplane_providers_cmd); + install_element(CONFIG_NODE, &zebra_dplane_queue_limit_cmd); + install_element(CONFIG_NODE, &no_zebra_dplane_queue_limit_cmd); } diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index f8417503ef..58cf6eb30f 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -37,6 +37,7 @@ #include #endif +#include "zebra/zebra_router.h" #include "zebra/debug.h" #include "zebra/interface.h" #include "zebra/rib.h" @@ -81,7 +82,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 +137,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 +157,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 +1253,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. */ @@ -1849,7 +1856,7 @@ static int zvni_gw_macip_del(struct interface *ifp, zebra_vni_t *zvni, /* mac entry should be present */ mac = zvni_mac_lookup(zvni, &n->emac); if (!mac) { - zlog_debug("MAC %s doesnt exists for neigh %s on VNI %u", + zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u", prefix_mac2str(&n->emac, buf1, sizeof(buf1)), ipaddr2str(ip, buf2, sizeof(buf2)), zvni->vni); return -1; @@ -2232,16 +2239,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 +2282,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 +2760,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 +2768,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. */ @@ -3097,7 +3114,9 @@ static int zvni_vtep_del_all(zebra_vni_t *zvni, int uninstall) */ static int zvni_vtep_install(zebra_vni_t *zvni, struct in_addr *vtep_ip) { - return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); + if (is_vxlan_flooding_head_end()) + return kernel_add_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); + return 0; } /* @@ -3114,6 +3133,28 @@ static int zvni_vtep_uninstall(zebra_vni_t *zvni, struct in_addr *vtep_ip) return kernel_del_vtep(zvni->vni, zvni->vxlan_if, vtep_ip); } +/* + * Install or uninstall flood entries in the kernel corresponding to + * remote VTEPs. This is invoked upon change to BUM handling. + */ +static void zvni_handle_flooding_remote_vteps(struct hash_backet *backet, + void *zvrf) +{ + zebra_vni_t *zvni; + zebra_vtep_t *zvtep; + + zvni = (zebra_vni_t *)backet->data; + if (!zvni) + return; + + for (zvtep = zvni->vteps; zvtep; zvtep = zvtep->next) { + if (is_vxlan_flooding_head_end()) + zvni_vtep_install(zvni, &zvtep->vtep_ip); + else + zvni_vtep_uninstall(zvni, &zvtep->vtep_ip); + } +} + /* * Cleanup VNI/VTEP and update kernel */ @@ -3577,7 +3618,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; @@ -3603,15 +3644,12 @@ static void *zl3vni_alloc(void *p) */ static zebra_l3vni_t *zl3vni_lookup(vni_t vni) { - struct zebra_ns *zns; zebra_l3vni_t tmp_l3vni; zebra_l3vni_t *zl3vni = NULL; - zns = zebra_ns_lookup(NS_DEFAULT); - assert(zns); memset(&tmp_l3vni, 0, sizeof(zebra_l3vni_t)); tmp_l3vni.vni = vni; - zl3vni = hash_lookup(zns->l3vni_table, &tmp_l3vni); + zl3vni = hash_lookup(zrouter.l3vni_table, &tmp_l3vni); return zl3vni; } @@ -3622,23 +3660,19 @@ static zebra_l3vni_t *zl3vni_lookup(vni_t vni) static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id) { zebra_l3vni_t tmp_zl3vni; - struct zebra_ns *zns = NULL; zebra_l3vni_t *zl3vni = NULL; - zns = zebra_ns_lookup(NS_DEFAULT); - assert(zns); - memset(&tmp_zl3vni, 0, sizeof(zebra_l3vni_t)); tmp_zl3vni.vni = vni; - zl3vni = hash_get(zns->l3vni_table, &tmp_zl3vni, zl3vni_alloc); + zl3vni = hash_get(zrouter.l3vni_table, &tmp_zl3vni, zl3vni_alloc); assert(zl3vni); zl3vni->vrf_id = 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, @@ -3656,12 +3690,8 @@ static zebra_l3vni_t *zl3vni_add(vni_t vni, vrf_id_t vrf_id) */ static int zl3vni_del(zebra_l3vni_t *zl3vni) { - struct zebra_ns *zns; zebra_l3vni_t *tmp_zl3vni; - zns = zebra_ns_lookup(NS_DEFAULT); - assert(zns); - /* free the list of l2vnis */ list_delete(&zl3vni->l2vnis); zl3vni->l2vnis = NULL; @@ -3675,7 +3705,7 @@ static int zl3vni_del(zebra_l3vni_t *zl3vni) zl3vni->nh_table = NULL; /* Free the VNI hash entry and allocated memory. */ - tmp_zl3vni = hash_release(zns->l3vni_table, zl3vni); + tmp_zl3vni = hash_release(zrouter.l3vni_table, zl3vni); if (tmp_zl3vni) XFREE(MTYPE_ZL3VNI, tmp_zl3vni); @@ -4524,7 +4554,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, if (use_json) vty_out(vty, "{}\n"); else - vty_out(vty, "%% L3-VNI %u doesnt exist\n", l3vni); + vty_out(vty, "%% L3-VNI %u doesn't exist\n", l3vni); return; } @@ -4534,7 +4564,7 @@ void zebra_vxlan_print_specific_rmac_l3vni(struct vty *vty, vni_t l3vni, vty_out(vty, "{}\n"); else vty_out(vty, - "%% Requested RMAC doesnt exist in L3-VNI %u", + "%% Requested RMAC doesn't exist in L3-VNI %u", l3vni); return; } @@ -4594,7 +4624,6 @@ void zebra_vxlan_print_rmacs_l3vni(struct vty *vty, vni_t l3vni, bool use_json) void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json) { - struct zebra_ns *zns = NULL; json_object *json = NULL; void *args[2]; @@ -4604,19 +4633,12 @@ void zebra_vxlan_print_rmacs_all_l3vni(struct vty *vty, bool use_json) return; } - zns = zebra_ns_lookup(NS_DEFAULT); - if (!zns) { - if (use_json) - vty_out(vty, "{}\n"); - return; - } - if (use_json) json = json_object_new_object(); args[0] = vty; args[1] = json; - hash_iterate(zns->l3vni_table, + hash_iterate(zrouter.l3vni_table, (void (*)(struct hash_backet *, void *))zl3vni_print_rmac_hash_all_vni, args); @@ -4719,7 +4741,6 @@ void zebra_vxlan_print_nh_l3vni(struct vty *vty, vni_t l3vni, bool use_json) void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json) { - struct zebra_ns *zns = NULL; json_object *json = NULL; void *args[2]; @@ -4729,16 +4750,12 @@ void zebra_vxlan_print_nh_all_l3vni(struct vty *vty, bool use_json) return; } - zns = zebra_ns_lookup(NS_DEFAULT); - if (!zns) - return; - if (use_json) json = json_object_new_object(); args[0] = vty; args[1] = json; - hash_iterate(zns->l3vni_table, + hash_iterate(zrouter.l3vni_table, (void (*)(struct hash_backet *, void *))zl3vni_print_nh_hash_all_vni, args); @@ -5233,21 +5250,16 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj) int num_l3vnis = 0; int num_vnis = 0; json_object *json = NULL; - struct zebra_ns *zns = NULL; struct zebra_vrf *zvrf = NULL; if (!is_evpn_enabled()) return; - zns = zebra_ns_lookup(NS_DEFAULT); - if (!zns) - return; - zvrf = vrf_info_lookup(VRF_DEFAULT); if (!zvrf) return; - num_l3vnis = hashcount(zns->l3vni_table); + num_l3vnis = hashcount(zrouter.l3vni_table); num_l2vnis = hashcount(zvrf->vni_table); num_vnis = num_l2vnis + num_l3vnis; @@ -5279,17 +5291,11 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, bool use_json) { json_object *json = NULL; - struct zebra_ns *zns = NULL; void *args[2]; if (!is_evpn_enabled()) return; - zns = zebra_ns_lookup(NS_DEFAULT); - if (!zns) - return; - - if (use_json) json = json_object_new_object(); else @@ -5306,7 +5312,7 @@ void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf, args); /* Display all L3-VNIs */ - hash_iterate(zns->l3vni_table, + hash_iterate(zrouter.l3vni_table, (void (*)(struct hash_backet *, void *))zl3vni_print_hash, args); @@ -6897,6 +6903,46 @@ int zebra_vxlan_vrf_delete(struct zebra_vrf *zvrf) return 0; } +/* + * Handle message from client to specify the flooding mechanism for + * BUM packets. The default is to do head-end (ingress) replication + * and the other supported option is to disable it. This applies to + * all BUM traffic and disabling it applies to both the transmit and + * receive direction. + */ +void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS) +{ + struct stream *s; + enum vxlan_flood_control flood_ctrl; + + if (zvrf_id(zvrf) != VRF_DEFAULT) { + zlog_err("EVPN flood control for non-default VRF %u", + zvrf_id(zvrf)); + return; + } + + s = msg; + STREAM_GETC(s, flood_ctrl); + + if (IS_ZEBRA_DEBUG_VXLAN) + zlog_debug("EVPN flood control %u, currently %u", + flood_ctrl, zvrf->vxlan_flood_ctrl); + + if (zvrf->vxlan_flood_ctrl == flood_ctrl) + return; + + zvrf->vxlan_flood_ctrl = flood_ctrl; + + /* Install or uninstall flood entries corresponding to + * remote VTEPs. + */ + hash_iterate(zvrf->vni_table, zvni_handle_flooding_remote_vteps, + zvrf); + +stream_failure: + return; +} + /* * Handle message from client to enable/disable advertisement of g/w macip * routes @@ -7073,12 +7119,14 @@ stream_failure: * When enabled, the VNI hash table will be built and MAC FDB table read; * when disabled, the entries should be deleted and remote VTEPs and MACs * uninstalled from the kernel. + * This also informs the setting for BUM handling at the time this change + * occurs; it is relevant only when specifying "learn". */ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) { struct stream *s = NULL; int advertise = 0; - struct zebra_ns *zns = NULL; + enum vxlan_flood_control flood_ctrl; if (zvrf_id(zvrf) != VRF_DEFAULT) { zlog_debug("EVPN VNI Adv for non-default VRF %u", @@ -7088,17 +7136,22 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) s = msg; STREAM_GETC(s, advertise); + STREAM_GETC(s, flood_ctrl); if (IS_ZEBRA_DEBUG_VXLAN) - zlog_debug("EVPN VNI Adv %s, currently %s", + zlog_debug("EVPN VNI Adv %s, currently %s, flood control %u", advertise ? "enabled" : "disabled", - is_evpn_enabled() ? "enabled" : "disabled"); + is_evpn_enabled() ? "enabled" : "disabled", + flood_ctrl); if (zvrf->advertise_all_vni == advertise) return; zvrf->advertise_all_vni = advertise; if (is_evpn_enabled()) { + /* Note BUM handling */ + zvrf->vxlan_flood_ctrl = flood_ctrl; + /* Build VNI hash table and inform BGP. */ zvni_build_hash_table(); @@ -7118,11 +7171,7 @@ void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS) hash_iterate(zvrf->vni_table, zvni_cleanup_all, zvrf); /* cleanup all l3vnis */ - zns = zebra_ns_lookup(NS_DEFAULT); - if (!zns) - return; - - hash_iterate(zns->l3vni_table, zl3vni_cleanup_all, NULL); + hash_iterate(zrouter.l3vni_table, zl3vni_cleanup_all, NULL); } stream_failure: @@ -7161,14 +7210,14 @@ void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) /* init the l3vni table */ void zebra_vxlan_ns_init(struct zebra_ns *zns) { - zns->l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp, - "Zebra VRF L3 VNI table"); + zrouter.l3vni_table = hash_create(l3vni_hash_keymake, l3vni_hash_cmp, + "Zebra VRF L3 VNI table"); } /* free l3vni table */ void zebra_vxlan_ns_disable(struct zebra_ns *zns) { - hash_free(zns->l3vni_table); + hash_free(zrouter.l3vni_table); } /* get the l3vni svi ifindex */ diff --git a/zebra/zebra_vxlan.h b/zebra/zebra_vxlan.h index a6c668785f..f03cd3d541 100644 --- a/zebra/zebra_vxlan.h +++ b/zebra/zebra_vxlan.h @@ -44,6 +44,15 @@ static inline int is_evpn_enabled() return zvrf ? zvrf->advertise_all_vni : 0; } +static inline int +is_vxlan_flooding_head_end() +{ + struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(VRF_DEFAULT); + + if (!zvrf) + return 0; + return (zvrf->vxlan_flood_ctrl == VXLAN_FLOOD_HEAD_END_REPL); +} /* VxLAN interface change flags of interest. */ #define ZEBRA_VXLIF_LOCAL_IP_CHANGE 0x1 @@ -57,6 +66,7 @@ extern void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_remote_vtep_add(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_remote_vtep_del(ZAPI_HANDLER_ARGS); +extern void zebra_vxlan_flood_control(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_subnet(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_gw_macip(ZAPI_HANDLER_ARGS); extern void zebra_vxlan_advertise_all_vni(ZAPI_HANDLER_ARGS); diff --git a/zebra/zebra_vxlan_null.c b/zebra/zebra_vxlan_null.c deleted file mode 100644 index 00c849a3d0..0000000000 --- a/zebra/zebra_vxlan_null.c +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Zebra VxLAN (EVPN) - * Copyright (C) 2016, 2017 Cumulus Networks, Inc. - * - * This file is part of FRR. - * - * FRR is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2, or (at your option) any - * later version. - * - * FRR is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with FRR; see the file COPYING. If not, write to the Free - * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - * 02111-1307, USA. - */ - -#include - -#include "if.h" -#include "zebra/debug.h" -#include "zebra/zserv.h" -#include "zebra/rib.h" -#include "zebra/zebra_vrf.h" -#include "zebra/zebra_l2.h" -#include "zebra/zebra_vxlan.h" - -void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni) -{ -} - -void zebra_vxlan_print_macs_all_vni(struct vty *vty, struct zebra_vrf *zvrf) -{ -} - -void zebra_vxlan_print_macs_all_vni_vtep(struct vty *vty, - struct zebra_vrf *zvrf, - struct in_addr vtep_ip) -{ -} - -void zebra_vxlan_print_specific_mac_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct ethaddr *mac) -{ -} - -void zebra_vxlan_print_macs_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) -{ -} - -void zebra_vxlan_print_neigh_vni(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni) -{ -} - -void zebra_vxlan_print_neigh_all_vni(struct vty *vty, struct zebra_vrf *zvrf) -{ -} - -void zebra_vxlan_print_specific_neigh_vni(struct vty *vty, - struct zebra_vrf *zvrf, vni_t vni, - struct ipaddr *ip) -{ -} - -void zebra_vxlan_print_neigh_vni_vtep(struct vty *vty, struct zebra_vrf *zvrf, - vni_t vni, struct in_addr vtep_ip) -{ -} - -void zebra_vxlan_print_vni(struct vty *vty, struct zebra_vrf *zvrf, vni_t vni) -{ -} - -void zebra_vxlan_print_vnis(struct vty *vty, struct zebra_vrf *zvrf) -{ -} - -void zebra_vxlan_print_evpn(struct vty *vty, bool uj) -{ -} - -void zebra_vxlan_print_rmacs_l3vni(struct vty *, vni_t, uint8_t) -{ -} - -void zebra_vxlan_print_rmacs_all_l3vni(struct vty *, uint8_t) -{ -} - -void zebra_vxlan_print_nh_l3vni(struct vty *, vni_t, uint8_t) -{ -} - -void zebra_vxlan_print_nh_all_l3vni(struct vty *, uint8_t) -{ -} - -void zebra_vxlan_print_l3vni(struct vty *vty, vni_t vni) -{ -} - -int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if) -{ - return 0; -} - -int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if) -{ - return 0; -} - -int zebra_vxlan_remote_macip_add(struct zserv *client, int sock, - unsigned short length, struct zebra_vrf *zvrf) -{ - return 0; -} - -int zebra_vxlan_remote_macip_del(struct zserv *client, int sock, - unsigned short length, struct zebra_vrf *zvrf) -{ - return 0; -} - -int zebra_vxlan_local_mac_add_update(struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid, - uint8_t sticky) -{ - return 0; -} - -int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) -{ - return 0; -} - -int zebra_vxlan_check_readd_remote_mac(struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) -{ - return 0; -} - -int zebra_vxlan_check_del_local_mac(struct interface *ifp, - struct interface *br_if, - struct ethaddr *mac, vlanid_t vid) -{ - return 0; -} - -int zebra_vxlan_if_up(struct interface *ifp) -{ - return 0; -} - -int zebra_vxlan_if_down(struct interface *ifp) -{ - return 0; -} - -int zebra_vxlan_if_add(struct interface *ifp) -{ - return 0; -} - -int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags) -{ - return 0; -} - -int zebra_vxlan_if_del(struct interface *ifp) -{ - return 0; -} - -int zebra_vxlan_remote_vtep_add(struct zserv *client, int sock, - unsigned short length, struct zebra_vrf *zvrf) -{ - return 0; -} - -int zebra_vxlan_remote_vtep_del(struct zserv *client, int sock, - unsigned short length, struct zebra_vrf *zvrf) -{ - return 0; -} - -int zebra_vxlan_advertise_all_vni(struct zserv *client, int sock, - unsigned short length, struct zebra_vrf *zvrf) -{ - return 0; -} - -void zebra_vxlan_init_tables(struct zebra_vrf *zvrf) -{ -} - -void zebra_vxlan_close_tables(struct zebra_vrf *zvrf) -{ -} - -void zebra_vxlan_cleanup_tables(struct zebra_vrf *zvrf) -{ -} diff --git a/zebra/zserv.h b/zebra/zserv.h index aaefd78eea..987c67635d 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -251,4 +251,7 @@ extern void zserv_close_client(struct zserv *client); extern void zserv_read_file(char *input); #endif +/* TODO */ +int zebra_finalize(struct thread *event); + #endif /* _ZEBRA_ZEBRA_H */