diff options
127 files changed, 1743 insertions, 429 deletions
diff --git a/bfdd/bfd.c b/bfdd/bfd.c index a2e84e928d..4354431820 100644 --- a/bfdd/bfd.c +++ b/bfdd/bfd.c @@ -600,6 +600,17 @@ skip_echo: bfd_recvtimer_update(bs); bfd_xmttimer_update(bs, bs->xmt_TO); } + if (bpc->bpc_cbit) { + if (BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CBIT)) + return; + + BFD_SET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT); + } else { + if (!BFD_CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CBIT)) + return; + + BFD_UNSET_FLAG(bs->flags, BFD_SESS_FLAG_CBIT); + } } static int bfd_session_update(struct bfd_session *bs, struct bfd_peer_cfg *bpc) @@ -1271,16 +1282,16 @@ void bs_to_bpc(struct bfd_session *bs, struct bfd_peer_cfg *bpc) static struct hash *bfd_id_hash; static struct hash *bfd_key_hash; -static unsigned int bfd_id_hash_do(void *p); -static unsigned int bfd_key_hash_do(void *p); +static unsigned int bfd_id_hash_do(const void *p); +static unsigned int bfd_key_hash_do(const void *p); static void _bfd_free(struct hash_bucket *hb, void *arg __attribute__((__unused__))); /* BFD hash for our discriminator. */ -static unsigned int bfd_id_hash_do(void *p) +static unsigned int bfd_id_hash_do(const void *p) { - struct bfd_session *bs = p; + const struct bfd_session *bs = p; return jhash_1word(bs->discrs.my_discr, 0); } @@ -1293,9 +1304,9 @@ static bool bfd_id_hash_cmp(const void *n1, const void *n2) } /* BFD hash for single hop. */ -static unsigned int bfd_key_hash_do(void *p) +static unsigned int bfd_key_hash_do(const void *p) { - struct bfd_session *bs = p; + const struct bfd_session *bs = p; return jhash(&bs->key, sizeof(bs->key), 0); } diff --git a/bfdd/bfd.h b/bfdd/bfd.h index 3f3d603832..213e905bf0 100644 --- a/bfdd/bfd.h +++ b/bfdd/bfd.h @@ -129,6 +129,12 @@ struct bfd_echo_pkt { flags |= (val & 0x3) << 6; \ } #define BFD_GETSTATE(flags) ((flags >> 6) & 0x3) +#define BFD_SETCBIT(flags, val) \ + { \ + if ((val)) \ + flags |= val; \ + } +#define BFD_GETCBIT(flags) (flags & BFD_FBIT) #define BFD_ECHO_VERSION 1 #define BFD_ECHO_PKT_LEN sizeof(struct bfd_echo_pkt) @@ -168,6 +174,7 @@ enum bfd_session_flags { */ BFD_SESS_FLAG_SHUTDOWN = 1 << 7, /* disable BGP peer function */ BFD_SESS_FLAG_CONFIG = 1 << 8, /* Session configured with bfd NB API */ + BFD_SESS_FLAG_CBIT = 1 << 9, /* CBIT is set */ }; #define BFD_SET_FLAG(field, flag) (field |= flag) @@ -210,6 +217,7 @@ struct bfd_session { uint8_t detect_mult; uint8_t remote_detect_mult; uint8_t mh_ttl; + uint8_t remote_cbit; /* Timers */ struct bfd_timers timers; diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c index 8edba05d12..f3acfa4167 100644 --- a/bfdd/bfd_packet.c +++ b/bfdd/bfd_packet.c @@ -221,6 +221,10 @@ void ptm_bfd_snd(struct bfd_session *bfd, int fbit) BFD_SETVER(cp.diag, BFD_VERSION); cp.flags = 0; BFD_SETSTATE(cp.flags, bfd->ses_state); + + if (BFD_CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_CBIT)) + BFD_SETCBIT(cp.flags, BFD_CBIT); + BFD_SETDEMANDBIT(cp.flags, BFD_DEF_DEMAND); /* @@ -646,6 +650,11 @@ int bfd_recv_cb(struct thread *t) ntohl(cp->timers.required_min_echo); bfd->remote_detect_mult = cp->detect_mult; + if (BFD_GETCBIT(cp->flags)) + bfd->remote_cbit = 1; + else + bfd->remote_cbit = 0; + /* State switch from section 6.2. */ bs_state_handler(bfd, BFD_GETSTATE(cp->flags)); diff --git a/bfdd/bfdctl.h b/bfdd/bfdctl.h index 0da1ca8df6..4ce23a8f27 100644 --- a/bfdd/bfdctl.h +++ b/bfdd/bfdctl.h @@ -88,6 +88,8 @@ struct bfd_peer_cfg { bool bpc_createonly; bool bpc_shutdown; + bool bpc_cbit; + /* Status information */ enum bfd_peer_status bpc_bps; uint32_t bpc_id; diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c index a12a3c196b..3e2ace6ea6 100644 --- a/bfdd/ptm_adapter.c +++ b/bfdd/ptm_adapter.c @@ -89,6 +89,7 @@ static void debug_printbpc(const char *func, unsigned int line, { char addr[3][128]; char timers[3][128]; + char cbit_str[10]; addr[0][0] = addr[1][0] = addr[2][0] = timers[0][0] = timers[1][0] = timers[2][0] = 0; @@ -117,9 +118,11 @@ static void debug_printbpc(const char *func, unsigned int line, snprintf(timers[2], sizeof(timers[2]), " detect-multiplier:%d", bpc->bpc_detectmultiplier); - log_debug("%s:%d: %s %s%s%s%s%s%s", func, line, + sprintf(cbit_str, "CB %x", bpc->bpc_cbit); + + log_debug("%s:%d: %s %s%s%s%s%s%s %s", func, line, bpc->bpc_mhop ? "multi-hop" : "single-hop", addr[0], addr[1], - addr[2], timers[0], timers[1], timers[2]); + addr[2], timers[0], timers[1], timers[2], cbit_str); } #define DEBUG_PRINTBPC(bpc) debug_printbpc(__FILE__, __LINE__, (bpc)) @@ -173,6 +176,7 @@ int ptm_bfd_notify(struct bfd_session *bs) * - AF_INET6: * - 16 bytes: ipv6 * - c: prefix length + * - c: cbit * * Commands: ZEBRA_BFD_DEST_REPLAY * @@ -219,6 +223,8 @@ int ptm_bfd_notify(struct bfd_session *bs) /* BFD source prefix information. */ _ptm_msg_address(msg, bs->key.family, &bs->key.local); + stream_putc(msg, bs->remote_cbit); + /* Write packet size. */ stream_putw_at(msg, 0, stream_get_endp(msg)); @@ -293,6 +299,7 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, * - 16 bytes: ipv6 address * - c: ifname length * - X bytes: interface name + * - c: bfd_cbit * * q(64), l(32), w(16), c(8) */ @@ -371,6 +378,8 @@ static int _ptm_msg_read(struct stream *msg, int command, vrf_id_t vrf_id, } } + STREAM_GETC(msg, bpc->bpc_cbit); + /* Sanity check: peer and local address must match IP types. */ if (bpc->bpc_local.sa_sin.sin_family != 0 && (bpc->bpc_local.sa_sin.sin_family diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c index c9f68d037b..497fb0749e 100644 --- a/bgpd/bgp_advertise.c +++ b/bgpd/bgp_advertise.c @@ -64,9 +64,9 @@ static void *baa_hash_alloc(void *p) return baa; } -unsigned int baa_hash_key(void *p) +unsigned int baa_hash_key(const void *p) { - struct bgp_advertise_attr *baa = (struct bgp_advertise_attr *)p; + const struct bgp_advertise_attr *baa = p; return attrhash_key_make(baa->attr); } diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h index cc845b93e7..7d2fdf1f0b 100644 --- a/bgpd/bgp_advertise.h +++ b/bgpd/bgp_advertise.h @@ -144,7 +144,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 unsigned int baa_hash_key(const void *p); 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); diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c index 92c37fabd2..05577cb8bd 100644 --- a/bgpd/bgp_aspath.c +++ b/bgpd/bgp_aspath.c @@ -2008,13 +2008,13 @@ struct aspath *aspath_str2aspath(const char *str) } /* Make hash value by raw aspath data. */ -unsigned int aspath_key_make(void *p) +unsigned int aspath_key_make(const void *p) { - struct aspath *aspath = (struct aspath *)p; + const struct aspath *aspath = p; unsigned int key = 0; if (!aspath->str) - aspath_str_update(aspath, false); + aspath_str_update((struct aspath *)aspath, false); key = jhash(aspath->str, aspath->str_len, 2334325); diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h index be5725c1ae..6f3d94cdb3 100644 --- a/bgpd/bgp_aspath.h +++ b/bgpd/bgp_aspath.h @@ -102,7 +102,7 @@ extern const char *aspath_print(struct aspath *); extern void aspath_print_vty(struct vty *, const char *, struct aspath *, const char *); extern void aspath_print_all_vty(struct vty *); -extern unsigned int aspath_key_make(void *); +extern unsigned int aspath_key_make(const void *); extern unsigned int aspath_get_first_as(struct aspath *); extern unsigned int aspath_get_last_as(struct aspath *); extern int aspath_loop_check(struct aspath *, as_t); diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index bdcce596ce..5a4105b400 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -139,7 +139,7 @@ int cluster_loop_check(struct cluster_list *cluster, struct in_addr originator) return 0; } -static unsigned int cluster_hash_key_make(void *p) +static unsigned int cluster_hash_key_make(const void *p) { const struct cluster_list *cluster = p; @@ -347,7 +347,7 @@ static void encap_unintern(struct bgp_attr_encap_subtlv **encapp, } } -static unsigned int encap_hash_key_make(void *p) +static unsigned int encap_hash_key_make(const void *p) { const struct bgp_attr_encap_subtlv *encap = p; @@ -432,7 +432,7 @@ void transit_unintern(struct transit *transit) } } -static unsigned int transit_hash_key_make(void *p) +static unsigned int transit_hash_key_make(const void *p) { const struct transit *transit = p; @@ -483,7 +483,7 @@ unsigned long int attr_unknown_count(void) return transit_hash->count; } -unsigned int attrhash_key_make(void *p) +unsigned int attrhash_key_make(const void *p) { const struct attr *attr = (struct attr *)p; uint32_t key = 0; diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index a6fdac9ebf..1592a8df4e 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -283,7 +283,7 @@ extern bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *, extern void bgp_dump_routes_attr(struct stream *, struct attr *, struct prefix *); extern bool attrhash_cmp(const void *arg1, const void *arg2); -extern unsigned int attrhash_key_make(void *); +extern unsigned int attrhash_key_make(const void *); extern void attr_show_all(struct vty *); extern unsigned long int attr_count(void); extern unsigned long int attr_unknown_count(void); diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c index a9c30acafb..57fef8e913 100644 --- a/bgpd/bgp_bfd.c +++ b/bgpd/bgp_bfd.c @@ -96,7 +96,7 @@ int bgp_bfd_is_peer_multihop(struct peer *peer) static void bgp_bfd_peer_sendmsg(struct peer *peer, int command) { struct bfd_info *bfd_info; - int multihop; + int multihop, cbit = 0; vrf_id_t vrf_id; bfd_info = (struct bfd_info *)peer->bfd_info; @@ -112,20 +112,30 @@ static void bgp_bfd_peer_sendmsg(struct peer *peer, int command) if ((command == ZEBRA_BFD_DEST_REGISTER) && multihop) SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_TYPE_MULTIHOP); } + /* while graceful restart with fwd path preserved + * and bfd controlplane check not configured is not kept + * keep bfd independent controlplane bit set to 1 + */ + if (!bgp_flag_check(peer->bgp, BGP_FLAG_GRACEFUL_RESTART) + && !bgp_flag_check(peer->bgp, BGP_FLAG_GR_PRESERVE_FWD) + && !CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); + + cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); if (peer->su.sa.sa_family == AF_INET) bfd_peer_sendmsg( zclient, bfd_info, AF_INET, &peer->su.sin.sin_addr, (peer->su_local) ? &peer->su_local->sin.sin_addr : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, multihop, command, 1, vrf_id); + peer->ttl, multihop, cbit, command, 1, vrf_id); else if (peer->su.sa.sa_family == AF_INET6) bfd_peer_sendmsg( zclient, bfd_info, AF_INET6, &peer->su.sin6.sin6_addr, (peer->su_local) ? &peer->su_local->sin6.sin6_addr : NULL, (peer->nexthop.ifp) ? peer->nexthop.ifp->name : NULL, - peer->ttl, multihop, command, 1, vrf_id); + peer->ttl, multihop, cbit, command, 1, vrf_id); } /* @@ -260,7 +270,8 @@ static int bgp_bfd_dest_replay(ZAPI_CALLBACK_ARGS) * down the peer if the BFD session went down from * * up. */ -static void bgp_bfd_peer_status_update(struct peer *peer, int status) +static void bgp_bfd_peer_status_update(struct peer *peer, int status, + int remote_cbit) { struct bfd_info *bfd_info; int old_status; @@ -280,6 +291,14 @@ static void bgp_bfd_peer_status_update(struct peer *peer, int status) bfd_get_status_str(status)); } if ((status == BFD_STATUS_DOWN) && (old_status == BFD_STATUS_UP)) { + if (CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE) && + CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE) && + !remote_cbit) { + zlog_info("%s BFD DOWN message ignored in the process" + " of graceful restart when C bit is cleared", + peer->host); + return; + } peer->last_reset = PEER_DOWN_BFD_DOWN; BGP_EVENT_ADD(peer, BGP_Stop); } @@ -303,23 +322,27 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS) struct prefix dp; struct prefix sp; int status; + int remote_cbit; - ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, + &remote_cbit, vrf_id); if (BGP_DEBUG(zebra, ZEBRA)) { char buf[2][PREFIX2STR_BUFFER]; prefix2str(&dp, buf[0], sizeof(buf[0])); if (ifp) { zlog_debug( - "Zebra: vrf %u interface %s bfd destination %s %s", + "Zebra: vrf %u interface %s bfd destination %s %s %s", vrf_id, ifp->name, buf[0], - bfd_get_status_str(status)); + bfd_get_status_str(status), + remote_cbit ? "(cbit on)" : ""); } else { prefix2str(&sp, buf[1], sizeof(buf[1])); zlog_debug( - "Zebra: vrf %u source %s bfd destination %s %s", + "Zebra: vrf %u source %s bfd destination %s %s %s", vrf_id, buf[1], buf[0], - bfd_get_status_str(status)); + bfd_get_status_str(status), + remote_cbit ? "(cbit on)" : ""); } } @@ -351,7 +374,8 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS) if (ifp && (ifp == peer->nexthop.ifp)) { bgp_bfd_peer_status_update(peer, - status); + status, + remote_cbit); } else { if (!peer->su_local) continue; @@ -381,7 +405,8 @@ static int bgp_bfd_dest_update(ZAPI_CALLBACK_ARGS) continue; bgp_bfd_peer_status_update(peer, - status); + status, + remote_cbit); } } } @@ -534,6 +559,9 @@ void bgp_bfd_peer_config_write(struct vty *vty, struct peer *peer, char *addr) if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG) && (bfd_info->type == BFD_TYPE_NOT_CONFIGURED)) vty_out(vty, " neighbor %s bfd\n", addr); + + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) + vty_out(vty, " neighbor %s bfd check-control-plane-failure\n", addr); } /* @@ -644,6 +672,73 @@ DEFUN_HIDDEN (neighbor_bfd_type, return CMD_SUCCESS; } +static int bgp_bfd_set_check_controlplane_failure_peer(struct vty *vty, struct peer *peer, + const char *no) +{ + struct bfd_info *bfd_info; + + if (!peer->bfd_info) { + if (no) + return CMD_SUCCESS; + vty_out(vty, "%% Specify bfd command first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + bfd_info = (struct bfd_info *)peer->bfd_info; + if (!no) { + if (!CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) { + SET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE); + bgp_bfd_update_peer(peer); + } + } else { + if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE)) { + UNSET_FLAG(bfd_info->flags, BFD_FLAG_BFD_CHECK_CONTROLPLANE); + bgp_bfd_update_peer(peer); + } + } + return CMD_SUCCESS; +} + + +DEFUN (neighbor_bfd_check_controlplane_failure, + neighbor_bfd_check_controlplane_failure_cmd, + "[no] neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "BFD support\n" + "Link dataplane status with BGP controlplane\n") +{ + const char *no = strmatch(argv[0]->text, "no") ? "no" : NULL; + int idx_peer = 0; + struct peer *peer; + struct peer_group *group; + struct listnode *node, *nnode; + int ret = CMD_SUCCESS; + + if (no) + idx_peer = 2; + else + idx_peer = 1; + peer = peer_and_group_lookup_vty(vty, argv[idx_peer]->arg); + if (!peer) { + vty_out(vty, "%% Specify remote-as or peer-group commands first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (!peer->bfd_info) { + if (no) + return CMD_SUCCESS; + vty_out(vty, "%% Specify bfd command first\n"); + return CMD_WARNING_CONFIG_FAILED; + } + if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) { + group = peer->group; + for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) + ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no); + } else + ret = bgp_bfd_set_check_controlplane_failure_peer(vty, peer, no); + return ret; + } + DEFUN (no_neighbor_bfd, no_neighbor_bfd_cmd, #if HAVE_BFDD > 0 @@ -718,6 +813,7 @@ void bgp_bfd_init(void) install_element(BGP_NODE, &neighbor_bfd_cmd); install_element(BGP_NODE, &neighbor_bfd_param_cmd); install_element(BGP_NODE, &neighbor_bfd_type_cmd); + install_element(BGP_NODE, &neighbor_bfd_check_controlplane_failure_cmd); install_element(BGP_NODE, &no_neighbor_bfd_cmd); install_element(BGP_NODE, &no_neighbor_bfd_type_cmd); } diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c index e308e963b5..b9a5784799 100644 --- a/bgpd/bgp_clist.c +++ b/bgpd/bgp_clist.c @@ -36,9 +36,9 @@ #include "bgpd/bgp_regex.h" #include "bgpd/bgp_clist.h" -static uint32_t bgp_clist_hash_key_community_list(void *data) +static uint32_t bgp_clist_hash_key_community_list(const void *data) { - struct community_list *cl = data; + struct community_list *cl = (struct community_list *) data; if (cl->name_hash) return cl->name_hash; diff --git a/bgpd/bgp_community.c b/bgpd/bgp_community.c index 67cd2be214..82762072df 100644 --- a/bgpd/bgp_community.c +++ b/bgpd/bgp_community.c @@ -574,7 +574,7 @@ char *community_str(struct community *com, bool make_json) /* Make hash value of community attribute. This function is used by hash package.*/ -unsigned int community_hash_make(struct community *com) +unsigned int community_hash_make(const struct community *com) { uint32_t *pnt = (uint32_t *)com->val; @@ -897,7 +897,7 @@ struct hash *community_hash(void) void community_init(void) { comhash = - hash_create((unsigned int (*)(void *))community_hash_make, + hash_create((unsigned int (*)(const void *))community_hash_make, (bool (*)(const void *, const void *))community_cmp, "BGP Community Hash"); } @@ -957,7 +957,7 @@ void bgp_compute_aggregate_community(struct bgp_aggregate *aggregate, */ if (aggregate->community_hash == NULL) aggregate->community_hash = hash_create( - (unsigned int (*)(void *))community_hash_make, + (unsigned int (*)(const void *))community_hash_make, (bool (*)(const void *, const void *))community_cmp, "BGP Aggregator community hash"); diff --git a/bgpd/bgp_community.h b/bgpd/bgp_community.h index 4ff4d214a5..f761a8f5e0 100644 --- a/bgpd/bgp_community.h +++ b/bgpd/bgp_community.h @@ -75,7 +75,7 @@ extern struct community *community_parse(uint32_t *, unsigned short); extern struct community *community_intern(struct community *); extern void community_unintern(struct community **); extern char *community_str(struct community *, bool make_json); -extern unsigned int community_hash_make(struct community *); +extern unsigned int community_hash_make(const struct community *); extern struct community *community_str2com(const char *); extern int community_match(const struct community *, const struct community *); extern bool community_cmp(const struct community *c1, diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 8ef398952d..76bd0e815e 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -241,7 +241,7 @@ void ecommunity_unintern(struct ecommunity **ecom) } /* Utinity function to make hash key. */ -unsigned int ecommunity_hash_make(void *arg) +unsigned int ecommunity_hash_make(const void *arg) { const struct ecommunity *ecom = arg; int size = ecom->size * ECOMMUNITY_SIZE; diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 165ab8fe14..79be4ee422 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -163,7 +163,7 @@ extern struct ecommunity *ecommunity_uniq_sort(struct ecommunity *); extern struct ecommunity *ecommunity_intern(struct ecommunity *); extern bool ecommunity_cmp(const void *arg1, const void *arg2); extern void ecommunity_unintern(struct ecommunity **); -extern unsigned int ecommunity_hash_make(void *); +extern unsigned int ecommunity_hash_make(const void *); extern struct ecommunity *ecommunity_str2com(const char *, int, int); extern char *ecommunity_ecom2str(struct ecommunity *, int, int); extern void ecommunity_strfree(char **s); diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 52aa923959..112e4b836c 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -83,9 +83,9 @@ static int evpn_vtep_ip_cmp(void *p1, void *p2) /* * Make hash key for ESI. */ -static unsigned int esi_hash_keymake(void *p) +static unsigned int esi_hash_keymake(const void *p) { - struct evpnes *pes = p; + const struct evpnes *pes = p; const void *pnt = (void *)pes->esi.val; return jhash(pnt, ESI_BYTES, 0xa5a5a55a); @@ -111,9 +111,9 @@ static bool esi_cmp(const void *p1, const void *p2) /* * Make vni hash key. */ -static unsigned int vni_hash_key_make(void *p) +static unsigned int vni_hash_key_make(const void *p) { - struct bgpevpn *vpn = p; + const struct bgpevpn *vpn = p; return (jhash_1word(vpn->vni, 0)); } @@ -143,10 +143,10 @@ static int vni_list_cmp(void *p1, void *p2) /* * Make vrf import route target hash key. */ -static unsigned int vrf_import_rt_hash_key_make(void *p) +static unsigned int vrf_import_rt_hash_key_make(const void *p) { - struct vrf_irt_node *irt = p; - char *pnt = irt->rt.val; + const struct vrf_irt_node *irt = p; + const char *pnt = irt->rt.val; return jhash(pnt, 8, 0x5abc1234); } @@ -259,10 +259,10 @@ static int is_vrf_present_in_irt_vrfs(struct list *vrfs, struct bgp *bgp_vrf) /* * Make import route target hash key. */ -static unsigned int import_rt_hash_key_make(void *p) +static unsigned int import_rt_hash_key_make(const void *p) { - struct irt_node *irt = p; - char *pnt = irt->rt.val; + const struct irt_node *irt = p; + const char *pnt = irt->rt.val; return jhash(pnt, 8, 0xdeadbeef); } diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c index 9e09d17893..67b0079c37 100644 --- a/bgpd/bgp_evpn_vty.c +++ b/bgpd/bgp_evpn_vty.c @@ -1554,14 +1554,15 @@ DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes, DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay, show_ip_bgp_l2vpn_evpn_all_overlay_cmd, - "show [ip] bgp l2vpn evpn all overlay", + "show [ip] bgp l2vpn evpn all overlay [json]", SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR "Display information about all EVPN NLRIs\n" - "Display BGP Overlay Information for prefixes\n") + "Display BGP Overlay Information for prefixes\n" + JSON_STR) { return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, SHOW_DISPLAY_OVERLAY, diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 9e37a60188..12ae1f841a 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -1115,8 +1115,6 @@ int bgp_stop(struct peer *peer) /* Reset peer synctime */ peer->synctime = 0; - - bgp_bfd_deregister_peer(peer); } /* stop keepalives */ diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c index c2f0baff76..bec3bdcb8d 100644 --- a/bgpd/bgp_keepalives.c +++ b/bgpd/bgp_keepalives.c @@ -131,9 +131,9 @@ static bool peer_hash_cmp(const void *f, const void *s) return p1->peer == p2->peer; } -static unsigned int peer_hash_key(void *arg) +static unsigned int peer_hash_key(const void *arg) { - struct pkat *pkat = arg; + const struct pkat *pkat = arg; return (uintptr_t)pkat->peer; } diff --git a/bgpd/bgp_lcommunity.c b/bgpd/bgp_lcommunity.c index 44766c9b6e..098374fa9f 100644 --- a/bgpd/bgp_lcommunity.c +++ b/bgpd/bgp_lcommunity.c @@ -301,7 +301,7 @@ char *lcommunity_str(struct lcommunity *lcom, bool make_json) } /* Utility function to make hash key. */ -unsigned int lcommunity_hash_make(void *arg) +unsigned int lcommunity_hash_make(const void *arg) { const struct lcommunity *lcom = arg; int size = lcom_length(lcom); diff --git a/bgpd/bgp_lcommunity.h b/bgpd/bgp_lcommunity.h index aa4e8c69fe..a512395492 100644 --- a/bgpd/bgp_lcommunity.h +++ b/bgpd/bgp_lcommunity.h @@ -63,7 +63,7 @@ extern struct lcommunity *lcommunity_uniq_sort(struct lcommunity *); extern struct lcommunity *lcommunity_intern(struct lcommunity *); extern bool lcommunity_cmp(const void *arg1, const void *arg2); extern void lcommunity_unintern(struct lcommunity **); -extern unsigned int lcommunity_hash_make(void *); +extern unsigned int lcommunity_hash_make(const void *); extern struct hash *lcommunity_hash(void); extern struct lcommunity *lcommunity_str2com(const char *); extern int lcommunity_match(const struct lcommunity *, diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c index 49b5854020..f19453fecb 100644 --- a/bgpd/bgp_mac.c +++ b/bgpd/bgp_mac.c @@ -40,9 +40,9 @@ struct bgp_self_mac { struct list *ifp_list; }; -static unsigned int bgp_mac_hash_key_make(void *data) +static unsigned int bgp_mac_hash_key_make(const void *data) { - struct bgp_self_mac *bsm = data; + const struct bgp_self_mac *bsm = data; return jhash(&bsm->macaddr, ETH_ALEN, 0xa5a5dead); } diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index de97b73c72..a8c507832c 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -114,7 +114,7 @@ static void bgp_tip_hash_free(void *addr) XFREE(MTYPE_TIP_ADDR, addr); } -static unsigned int bgp_tip_hash_key_make(void *p) +static unsigned int bgp_tip_hash_key_make(const void *p) { const struct tip_addr *addr = p; @@ -237,7 +237,7 @@ static void bgp_address_hash_free(void *data) XFREE(MTYPE_BGP_ADDR, addr); } -static unsigned int bgp_address_hash_key_make(void *p) +static unsigned int bgp_address_hash_key_make(const void *p) { const struct bgp_addr *addr = p; @@ -505,6 +505,77 @@ int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer) return (ret); } +int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer) +{ + struct bgp_node *rn1; + struct bgp_node *rn2; + struct prefix p; + int ret; + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_BITLEN; + p.u.prefix6 = nexthop; + + rn1 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p); + if (!rn1) + return 0; + + p.family = AF_INET6; + p.prefixlen = IPV6_MAX_BITLEN; + p.u.prefix6 = peer->su.sin6.sin6_addr; + + rn2 = bgp_node_match(peer->bgp->connected_table[AFI_IP6], &p); + if (!rn2) { + bgp_unlock_node(rn1); + return 0; + } + + ret = (rn1 == rn2) ? 1 : 0; + + bgp_unlock_node(rn1); + bgp_unlock_node(rn2); + + return ret; +} + +int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, + struct update_subgroup *subgrp) +{ + struct bgp_node *rn1 = NULL, *rn2 = NULL; + struct peer_af *paf = NULL; + struct prefix p = {0}, np = {0}; + struct bgp *bgp = NULL; + + np.family = AF_INET6; + np.prefixlen = IPV6_MAX_BITLEN; + np.u.prefix6 = nexthop; + + p.family = AF_INET; + p.prefixlen = IPV6_MAX_BITLEN; + + bgp = SUBGRP_INST(subgrp); + rn1 = bgp_node_match(bgp->connected_table[AFI_IP6], &np); + if (!rn1) + return 0; + + SUBGRP_FOREACH_PEER (subgrp, paf) { + + p.u.prefix6 = paf->peer->su.sin6.sin6_addr; + rn2 = bgp_node_match(bgp->connected_table[AFI_IP6], &p); + if (rn1 == rn2) { + bgp_unlock_node(rn1); + bgp_unlock_node(rn2); + return 1; + } + + if (rn2) + bgp_unlock_node(rn2); + } + + bgp_unlock_node(rn1); + return 0; +} + int bgp_subgrp_multiaccess_check_v4(struct in_addr nexthop, struct update_subgroup *subgrp) { diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index f06fae5706..d35f1ad520 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -74,11 +74,19 @@ struct tip_addr { int refcnt; }; +struct bgp_addrv6 { + struct in6_addr addrv6; + struct list *ifp_name_list; +}; + 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, struct update_subgroup *subgrp); -extern int bgp_multiaccess_check_v4(struct in_addr, struct peer *); +extern int bgp_subgrp_multiaccess_check_v6(struct in6_addr nexthop, + struct update_subgroup *subgrp); +extern int bgp_multiaccess_check_v4(struct in_addr nexthop, struct peer *peer); +extern int bgp_multiaccess_check_v6(struct in6_addr nexthop, struct peer *peer); extern int bgp_config_write_scan_time(struct vty *); extern int bgp_nexthop_self(struct bgp *, struct in_addr); extern struct bgp_nexthop_cache *bnc_new(void); diff --git a/bgpd/bgp_pbr.c b/bgpd/bgp_pbr.c index 0fddfa75a1..5eef6ac6cc 100644 --- a/bgpd/bgp_pbr.c +++ b/bgpd/bgp_pbr.c @@ -964,9 +964,9 @@ static void *bgp_pbr_match_entry_alloc_intern(void *arg) return new; } -uint32_t bgp_pbr_match_hash_key(void *arg) +uint32_t bgp_pbr_match_hash_key(const void *arg) { - struct bgp_pbr_match *pbm = (struct bgp_pbr_match *)arg; + const struct bgp_pbr_match *pbm = arg; uint32_t key; key = jhash_1word(pbm->vrf_id, 0x4312abde); @@ -1019,9 +1019,9 @@ bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2) return true; } -uint32_t bgp_pbr_rule_hash_key(void *arg) +uint32_t bgp_pbr_rule_hash_key(const void *arg) { - struct bgp_pbr_rule *pbr = (struct bgp_pbr_rule *)arg; + const struct bgp_pbr_rule *pbr = arg; uint32_t key; key = prefix_hash_key(&pbr->src); @@ -1057,12 +1057,12 @@ bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2) return true; } -uint32_t bgp_pbr_match_entry_hash_key(void *arg) +uint32_t bgp_pbr_match_entry_hash_key(const void *arg) { - struct bgp_pbr_match_entry *pbme; + const struct bgp_pbr_match_entry *pbme; uint32_t key; - pbme = (struct bgp_pbr_match_entry *)arg; + pbme = arg; key = prefix_hash_key(&pbme->src); key = jhash_1word(prefix_hash_key(&pbme->dst), key); key = jhash(&pbme->dst_port_min, 2, key); @@ -1111,12 +1111,12 @@ bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2) return true; } -uint32_t bgp_pbr_action_hash_key(void *arg) +uint32_t bgp_pbr_action_hash_key(const void *arg) { - struct bgp_pbr_action *pbra; + const struct bgp_pbr_action *pbra; uint32_t key; - pbra = (struct bgp_pbr_action *)arg; + pbra = arg; key = jhash_1word(pbra->table_id, 0x4312abde); key = jhash_1word(pbra->fwmark, key); return key; diff --git a/bgpd/bgp_pbr.h b/bgpd/bgp_pbr.h index f7fddac7fb..b368d8892d 100644 --- a/bgpd/bgp_pbr.h +++ b/bgpd/bgp_pbr.h @@ -273,16 +273,16 @@ extern struct bgp_pbr_match *bgp_pbr_match_iptable_lookup(vrf_id_t vrf_id, extern void bgp_pbr_cleanup(struct bgp *bgp); extern void bgp_pbr_init(struct bgp *bgp); -extern uint32_t bgp_pbr_rule_hash_key(void *arg); +extern uint32_t bgp_pbr_rule_hash_key(const void *arg); extern bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2); -extern uint32_t bgp_pbr_action_hash_key(void *arg); +extern uint32_t bgp_pbr_action_hash_key(const void *arg); 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 uint32_t bgp_pbr_match_entry_hash_key(const void *arg); 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 uint32_t bgp_pbr_match_hash_key(const void *arg); extern bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index f3a69d4b25..4f89c8b5f7 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -1888,13 +1888,28 @@ int subgroup_announce_check(struct bgp_node *rn, struct bgp_path_info *pi, * Note: 3rd party nexthop currently implemented for * IPv4 only. */ - if (!bgp_subgrp_multiaccess_check_v4(piattr->nexthop, - subgrp)) + if ((p->family == AF_INET) && + (!bgp_subgrp_multiaccess_check_v4( + piattr->nexthop, + subgrp))) subgroup_announce_reset_nhop( (peer_cap_enhe(peer, afi, safi) ? AF_INET6 : p->family), - attr); + attr); + + if ((p->family == AF_INET6) && + (!bgp_subgrp_multiaccess_check_v6( + piattr->mp_nexthop_global, + subgrp))) + subgroup_announce_reset_nhop( + (peer_cap_enhe(peer, afi, safi) + ? AF_INET6 + : p->family), + attr); + + + } else if (CHECK_FLAG(pi->flags, BGP_PATH_ANNC_NH_SELF)) { /* * This flag is used for leaked vpn-vrf routes @@ -7571,21 +7586,26 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, json_object *json_paths) { struct attr *attr; - char buf[BUFSIZ]; + char buf[BUFSIZ] = {0}; json_object *json_path = NULL; - - if (json_paths) - json_path = json_object_new_object(); + json_object *json_nexthop = NULL; + json_object *json_overlay = NULL; if (!path->extra) return; + if (json_paths) { + json_path = json_object_new_object(); + json_overlay = json_object_new_object(); + json_nexthop = json_object_new_object(); + } + /* short status lead text */ route_vty_short_status_out(vty, path, json_path); /* print prefix and mask */ if (!display) - route_vty_out_route(p, vty, NULL); + route_vty_out_route(p, vty, json_path); else vty_out(vty, "%*s", 17, " "); @@ -7597,35 +7617,69 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, switch (af) { case AF_INET: - vty_out(vty, "%-16s", - inet_ntop(af, &attr->mp_nexthop_global_in, buf, - BUFSIZ)); + inet_ntop(af, &attr->mp_nexthop_global_in, buf, BUFSIZ); + if (!json_path) { + vty_out(vty, "%-16s", buf); + } else { + json_object_string_add(json_nexthop, "ip", buf); + + json_object_string_add(json_nexthop, "afi", + "ipv4"); + + json_object_object_add(json_path, "nexthop", + json_nexthop); + } break; case AF_INET6: - vty_out(vty, "%s(%s)", - inet_ntop(af, &attr->mp_nexthop_global, buf, - BUFSIZ), - inet_ntop(af, &attr->mp_nexthop_local, buf1, - BUFSIZ)); + inet_ntop(af, &attr->mp_nexthop_global, buf, BUFSIZ); + inet_ntop(af, &attr->mp_nexthop_local, buf1, BUFSIZ); + if (!json_path) { + vty_out(vty, "%s(%s)", buf, buf1); + } else { + json_object_string_add(json_nexthop, + "ipv6Global", buf); + + json_object_string_add(json_nexthop, + "ipv6LinkLocal", buf1); + + json_object_string_add(json_nexthop, "afi", + "ipv6"); + + json_object_object_add(json_path, "nexthop", + json_nexthop); + } break; default: - vty_out(vty, "?"); + if (!json_path) { + vty_out(vty, "?"); + } else { + json_object_string_add(json_nexthop, "Error", + "Unsupported address-family"); + } } char *str = esi2str(&(attr->evpn_overlay.eth_s_id)); - vty_out(vty, "%s", str); + if (!json_path) + vty_out(vty, "%s", str); + else + json_object_string_add(json_overlay, "esi", str); + XFREE(MTYPE_TMP, str); if (is_evpn_prefix_ipaddr_v4((struct prefix_evpn *)p)) { - vty_out(vty, "/%s", - inet_ntoa(attr->evpn_overlay.gw_ip.ipv4)); + inet_ntop(AF_INET, &(attr->evpn_overlay.gw_ip.ipv4), + buf, BUFSIZ); } else if (is_evpn_prefix_ipaddr_v6((struct prefix_evpn *)p)) { - vty_out(vty, "/%s", - inet_ntop(AF_INET6, - &(attr->evpn_overlay.gw_ip.ipv6), buf, - BUFSIZ)); + inet_ntop(AF_INET6, &(attr->evpn_overlay.gw_ip.ipv6), + buf, BUFSIZ); } + + if (!json_path) + vty_out(vty, "/%s", buf); + else + json_object_string_add(json_overlay, "gw", buf); + if (attr->ecommunity) { char *mac = NULL; struct ecommunity_val *routermac = ecommunity_lookup( @@ -7634,13 +7688,25 @@ void route_vty_out_overlay(struct vty *vty, struct prefix *p, if (routermac) mac = ecom_mac2str((char *)routermac->val); if (mac) { - vty_out(vty, "/%s", (char *)mac); + if (!json_path) { + vty_out(vty, "/%s", (char *)mac); + } else { + json_object_string_add(json_overlay, + "rmac", mac); + } XFREE(MTYPE_TMP, mac); } } - vty_out(vty, "\n"); - } + if (!json_path) { + vty_out(vty, "\n"); + } else { + json_object_object_add(json_path, "overlay", + json_overlay); + + json_object_array_add(json_paths, json_path); + } + } } /* dampening route */ diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c index 57717bf59b..d0be2471af 100644 --- a/bgpd/bgp_updgrp.c +++ b/bgpd/bgp_updgrp.c @@ -288,7 +288,7 @@ static void *updgrp_hash_alloc(void *p) * 16. Local-as should match, if configured. * ) */ -static unsigned int updgrp_hash_key_make(void *p) +static unsigned int updgrp_hash_key_make(const void *p) { const struct update_group *updgrp; const struct peer *peer; diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 3556b236a7..688abae0e4 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -554,9 +554,9 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt, mod_v6nhg = &peer->nexthop.v6_global; gnh_modified = 1; } else if ( - peer->sort == BGP_PEER_EBGP - && !CHECK_FLAG( - vec->flags, + (peer->sort == BGP_PEER_EBGP) + && (!bgp_multiaccess_check_v6(v6nhglobal, peer)) + && !CHECK_FLAG(vec->flags, BPKT_ATTRVEC_FLAGS_RMAP_NH_UNCHANGED) && !peer_af_flag_check( peer, nhafi, paf->safi, diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index bce6fb48c7..880b877806 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -119,6 +119,7 @@ static enum node_type bgp_node_type(afi_t afi, safi_t safi) case AFI_L2VPN: return BGP_EVPN_NODE; break; + case AFI_UNSPEC: case AFI_MAX: // We should never be here but to clarify the switch statement.. return BGP_IPV4_NODE; diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index 6183bbd471..c0f1f3184a 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -812,9 +812,9 @@ int peer_cmp(struct peer *p1, struct peer *p2) return sockunion_cmp(&p1->su, &p2->su); } -static unsigned int peer_hash_key_make(void *p) +static unsigned int peer_hash_key_make(const void *p) { - struct peer *peer = p; + const struct peer *peer = p; return sockunion_hash(&peer->su); } diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst index 1e165a2444..09f12ec436 100644 --- a/doc/developer/topotests.rst +++ b/doc/developer/topotests.rst @@ -189,13 +189,12 @@ If found, then this is added with context (calling test) to Compiling for GCC AddressSanitizer requires to use ``gcc`` as a linker as well (instead of ``ld``). Here is a suggest way to compile frr with AddressSanitizer -for ``stable/3.0`` branch: +for ``master`` branch: .. code:: shell git clone https://github.com/FRRouting/frr.git cd frr - git checkout stable/3.0 ./bootstrap.sh export CC=gcc export CFLAGS="-O1 -g -fsanitize=address -fno-omit-frame-pointer" @@ -208,7 +207,8 @@ for ``stable/3.0`` branch: --enable-exampledir=/usr/lib/frr/examples \ --with-moduledir=/usr/lib/frr/modules \ --enable-multipath=0 --enable-rtadv \ - --enable-tcp-zebra --enable-fpm --enable-pimd + --enable-tcp-zebra --enable-fpm --enable-pimd \ + --enable-sharpd make sudo make install # Create symlink for vtysh, so topotest finds it in /usr/lib/frr diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst index a7c5cf28bc..33bc77049e 100644 --- a/doc/user/bfd.rst +++ b/doc/user/bfd.rst @@ -174,6 +174,21 @@ The following commands are available inside the BGP configuration node. Removes any notification registration for this neighbor. +.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure +.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure + + Allow to write CBIT independence in BFD outgoing packets. Also allow to + read both C-BIT value of BFD and lookup BGP peer status. This command is + useful when a BFD down event is caught, while the BGP peer requested that + local BGP keeps the remote BGP entries as staled if such issue is detected. + This is the case when graceful restart is enabled, and it is wished to + ignore the BD event while waiting for the remote router to restart. + +.. index:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure +.. clicmd:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure + + Disallow to write CBIT independence in BFD outgoing packets. Also disallow + to ignore BFD down notification. This is the default behaviour. .. _bfd-ospf-peer-config: diff --git a/isisd/fabricd.c b/isisd/fabricd.c index 96af28f0a1..b9c27d51bd 100644 --- a/isisd/fabricd.c +++ b/isisd/fabricd.c @@ -108,9 +108,9 @@ static void neighbor_lists_clear(struct fabricd *f) hash_clean(f->neighbors_neighbors, neighbor_entry_del_void); } -static unsigned neighbor_entry_hash_key(void *np) +static unsigned neighbor_entry_hash_key(const void *np) { - struct neighbor_entry *n = np; + const struct neighbor_entry *n = np; return jhash(n->id, sizeof(n->id), 0x55aa5a5a); } diff --git a/isisd/isis_bfd.c b/isisd/isis_bfd.c index fccef0169e..fa89c80049 100644 --- a/isisd/isis_bfd.c +++ b/isisd/isis_bfd.c @@ -98,7 +98,8 @@ static int isis_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS) struct prefix dst_ip; int status; - ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, vrf_id); + ifp = bfd_get_peer_info(zclient->ibuf, &dst_ip, NULL, &status, + NULL, vrf_id); if (!ifp || dst_ip.family != AF_INET) return 0; @@ -217,6 +218,7 @@ static void bfd_handle_adj_down(struct isis_adjacency *adj) adj->circuit->interface->name, 0, /* ttl */ 0, /* multihop */ + 1, /* control plane independent bit is on */ ZEBRA_BFD_DEST_DEREGISTER, 0, /* set_flag */ VRF_DEFAULT); @@ -258,6 +260,7 @@ static void bfd_handle_adj_up(struct isis_adjacency *adj, int command) circuit->interface->name, 0, /* ttl */ 0, /* multihop */ + 1, /* control plane independent bit is on */ command, 0, /* set flag */ VRF_DEFAULT); diff --git a/isisd/isis_spf_private.h b/isisd/isis_spf_private.h index 3a2a52afac..a8185a8be0 100644 --- a/isisd/isis_spf_private.h +++ b/isisd/isis_spf_private.h @@ -79,9 +79,9 @@ struct isis_vertex_queue { }; __attribute__((__unused__)) -static unsigned isis_vertex_queue_hash_key(void *vp) +static unsigned isis_vertex_queue_hash_key(const void *vp) { - struct isis_vertex *vertex = vp; + const struct isis_vertex *vertex = vp; if (VTYPE_IP(vertex->type)) { uint32_t key; diff --git a/isisd/isis_tx_queue.c b/isisd/isis_tx_queue.c index 6f46e6bec0..507fd489bc 100644 --- a/isisd/isis_tx_queue.c +++ b/isisd/isis_tx_queue.c @@ -50,9 +50,9 @@ struct isis_tx_queue_entry { struct isis_tx_queue *queue; }; -static unsigned tx_queue_hash_key(void *p) +static unsigned tx_queue_hash_key(const void *p) { - struct isis_tx_queue_entry *e = p; + const struct isis_tx_queue_entry *e = p; uint32_t id_key = jhash(e->lsp->hdr.lsp_id, ISIS_SYS_ID_LEN + 2, 0x55aa5a5a); @@ -127,8 +127,8 @@ void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, uint32_t min_tx, */ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, int family, void *dst_ip, void *src_ip, char *if_name, - int ttl, int multihop, int command, int set_flag, - vrf_id_t vrf_id) + int ttl, int multihop, int cbit, int command, + int set_flag, vrf_id_t vrf_id) { struct stream *s; int ret; @@ -208,6 +208,11 @@ void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, stream_putc(s, 0); } } + /* cbit */ + if (cbit) + stream_putc(s, 1); + else + stream_putc(s, 0); stream_putw_at(s, 0, stream_get_endp(s)); @@ -253,11 +258,13 @@ const char *bfd_get_command_dbg_str(int command) */ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, struct prefix *sp, int *status, + int *remote_cbit, vrf_id_t vrf_id) { unsigned int ifindex; struct interface *ifp = NULL; int plen; + int local_remote_cbit; /* Get interface index. */ ifindex = stream_getl(s); @@ -292,6 +299,9 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, stream_get(&sp->u.prefix, s, plen); sp->prefixlen = stream_getc(s); } + local_remote_cbit = stream_getc(s); + if (remote_cbit) + *remote_cbit = local_remote_cbit; return ifp; } @@ -48,6 +48,8 @@ struct bfd_gbl { #define BFD_FLAG_PARAM_CFG (1 << 0) /* parameters have been configured */ #define BFD_FLAG_BFD_REG (1 << 1) /* Peer registered with BFD */ #define BFD_FLAG_BFD_TYPE_MULTIHOP (1 << 2) /* Peer registered with BFD as multihop */ +#define BFD_FLAG_BFD_CBIT_ON (1 << 3) /* Peer registered with CBIT set to on */ +#define BFD_FLAG_BFD_CHECK_CONTROLPLANE (1 << 4) /* BFD and controlplane daemon are linked */ #define BFD_STATUS_UNKNOWN (1 << 0) /* BFD session status never received */ #define BFD_STATUS_DOWN (1 << 1) /* BFD session status is down */ @@ -83,13 +85,14 @@ extern void bfd_set_param(struct bfd_info **bfd_info, uint32_t min_rx, int *command); extern void bfd_peer_sendmsg(struct zclient *zclient, struct bfd_info *bfd_info, int family, void *dst_ip, void *src_ip, - char *if_name, int ttl, int multihop, int command, - int set_flag, vrf_id_t vrf_id); + char *if_name, int ttl, int multihop, int cbit, + int command, int set_flag, vrf_id_t vrf_id); extern const char *bfd_get_command_dbg_str(int command); extern struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp, struct prefix *sp, int *status, + int *remote_cbit, vrf_id_t vrf_id); const char *bfd_get_status_str(int status); diff --git a/lib/command.c b/lib/command.c index d6fd1fa561..b7a323e358 100644 --- a/lib/command.c +++ b/lib/command.c @@ -332,7 +332,7 @@ int argv_find(struct cmd_token **argv, int argc, const char *text, int *index) return found; } -static unsigned int cmd_hash_key(void *p) +static unsigned int cmd_hash_key(const void *p) { int size = sizeof(p); diff --git a/lib/distribute.c b/lib/distribute.c index be40bd2603..2aa6b927fb 100644 --- a/lib/distribute.c +++ b/lib/distribute.c @@ -131,7 +131,7 @@ static struct distribute *distribute_get(struct distribute_ctx *ctx, return ret; } -static unsigned int distribute_hash_make(void *arg) +static unsigned int distribute_hash_make(const void *arg) { const struct distribute *dist = arg; diff --git a/lib/ferr.c b/lib/ferr.c index d7fa1a84f8..65c0cf886d 100644 --- a/lib/ferr.c +++ b/lib/ferr.c @@ -72,9 +72,9 @@ static bool ferr_hash_cmp(const void *a, const void *b) return f_a->code == f_b->code; } -static inline unsigned int ferr_hash_key(void *a) +static inline unsigned int ferr_hash_key(const void *a) { - struct log_ref *f = a; + const struct log_ref *f = a; return f->code; } diff --git a/lib/hash.c b/lib/hash.c index 884c8f22af..fad7de5138 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -37,7 +37,7 @@ static pthread_mutex_t _hashes_mtx = PTHREAD_MUTEX_INITIALIZER; static struct list *_hashes; struct hash *hash_create_size(unsigned int size, - unsigned int (*hash_key)(void *), + unsigned int (*hash_key)(const void *), bool (*hash_cmp)(const void *, const void *), const char *name) { @@ -66,7 +66,7 @@ struct hash *hash_create_size(unsigned int size, return hash; } -struct hash *hash_create(unsigned int (*hash_key)(void *), +struct hash *hash_create(unsigned int (*hash_key)(const void *), bool (*hash_cmp)(const void *, const void *), const char *name) { diff --git a/lib/hash.h b/lib/hash.h index 60c412b8e0..c56a98d50c 100644 --- a/lib/hash.h +++ b/lib/hash.h @@ -79,7 +79,7 @@ struct hash { unsigned int max_size; /* Key make function. */ - unsigned int (*hash_key)(void *); + unsigned int (*hash_key)(const void *); /* Data compare function. */ bool (*hash_cmp)(const void *, const void *); @@ -123,7 +123,7 @@ struct hash { * Returns: * a new hash table */ -extern struct hash *hash_create(unsigned int (*hash_key)(void *), +extern struct hash *hash_create(unsigned int (*hash_key)(const void *), bool (*hash_cmp)(const void *, const void *), const char *name); @@ -158,7 +158,7 @@ extern struct hash *hash_create(unsigned int (*hash_key)(void *), * a new hash table */ extern struct hash * -hash_create_size(unsigned int size, unsigned int (*hash_key)(void *), +hash_create_size(unsigned int size, unsigned int (*hash_key)(const void *), bool (*hash_cmp)(const void *, const void *), const char *name); diff --git a/lib/if_rmap.c b/lib/if_rmap.c index b0802da961..ca6f512ec6 100644 --- a/lib/if_rmap.c +++ b/lib/if_rmap.c @@ -107,7 +107,7 @@ static struct if_rmap *if_rmap_get(struct if_rmap_ctx *ctx, const char *ifname) return ret; } -static unsigned int if_rmap_hash_make(void *data) +static unsigned int if_rmap_hash_make(const void *data) { const struct if_rmap *if_rmap = data; diff --git a/lib/northbound.c b/lib/northbound.c index e8b3e46c19..dbf90c58d4 100644 --- a/lib/northbound.c +++ b/lib/northbound.c @@ -1654,7 +1654,7 @@ static bool running_config_entry_cmp(const void *value1, const void *value2) return strmatch(c1->xpath, c2->xpath); } -static unsigned int running_config_entry_key_make(void *value) +static unsigned int running_config_entry_key_make(const void *value) { return string_hash_make(value); } diff --git a/lib/routemap.c b/lib/routemap.c index 0c75be3323..3542994e65 100644 --- a/lib/routemap.c +++ b/lib/routemap.c @@ -623,7 +623,7 @@ struct route_map_list { static struct route_map_list route_map_master = {NULL, NULL, NULL, NULL, NULL}; struct hash *route_map_master_hash = NULL; -static unsigned int route_map_hash_key_make(void *p) +static unsigned int route_map_hash_key_make(const void *p) { const struct route_map *map = p; return string_hash_make(map->name); @@ -673,7 +673,7 @@ struct route_map_dep { /* Hashes maintaining dependency between various sublists used by route maps */ struct hash *route_map_dep_hash[ROUTE_MAP_DEP_MAX]; -static unsigned int route_map_dep_hash_make_key(void *p); +static unsigned int route_map_dep_hash_make_key(const void *p); 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 *); @@ -906,6 +906,8 @@ static const char *route_map_type_str(enum route_map_type type) return ""; break; } + + return ""; } static int route_map_empty(struct route_map *map) @@ -1287,7 +1289,6 @@ int route_map_add_match(struct route_map_index *index, const char *match_name, struct route_map_rule *next; struct route_map_rule_cmd *cmd; void *compile; - int replaced = 0; /* First lookup rule for add match statement. */ cmd = route_map_lookup_match(match_name); @@ -1317,7 +1318,6 @@ int route_map_add_match(struct route_map_index *index, const char *match_name, } route_map_rule_delete(&index->match_list, rule); - replaced = 1; } } @@ -1379,7 +1379,6 @@ int route_map_add_set(struct route_map_index *index, const char *set_name, struct route_map_rule *next; struct route_map_rule_cmd *cmd; void *compile; - int replaced = 0; cmd = route_map_lookup_set(set_name); if (cmd == NULL) @@ -1398,10 +1397,8 @@ int route_map_add_set(struct route_map_index *index, const char *set_name, route_map_index. */ for (rule = index->set_list.head; rule; rule = next) { next = rule->next; - if (rule->cmd == cmd) { + if (rule->cmd == cmd) route_map_rule_delete(&index->set_list, rule); - replaced = 1; - } } /* Add new route map match rule. */ @@ -1709,7 +1706,7 @@ static void *route_map_name_hash_alloc(void *p) return ((void *)XSTRDUP(MTYPE_ROUTE_MAP_NAME, (const char *)p)); } -static unsigned int route_map_dep_hash_make_key(void *p) +static unsigned int route_map_dep_hash_make_key(const void *p) { return (string_hash_make((char *)p)); } diff --git a/lib/thread.c b/lib/thread.c index 5ca859a74d..9489e3e923 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -63,7 +63,7 @@ static struct list *masters; static void thread_free(struct thread_master *master, struct thread *thread); /* CLI start ---------------------------------------------------------------- */ -static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) +static unsigned int cpu_record_hash_key(const struct cpu_thread_history *a) { int size = sizeof(a->func); @@ -433,7 +433,7 @@ struct thread_master *thread_master_create(const char *name) sizeof(struct thread *) * rv->fd_limit); rv->cpu_record = hash_create_size( - 8, (unsigned int (*)(void *))cpu_record_hash_key, + 8, (unsigned int (*)(const void *))cpu_record_hash_key, (bool (*)(const void *, const void *))cpu_record_hash_cmp, "Thread Hash"); @@ -362,9 +362,9 @@ struct vrf_bit_set { bool set; }; -static unsigned int vrf_hash_bitmap_key(void *data) +static unsigned int vrf_hash_bitmap_key(const void *data) { - struct vrf_bit_set *bit = data; + const struct vrf_bit_set *bit = data; return bit->vrf_id; } diff --git a/lib/wheel.c b/lib/wheel.c index 69d2fa48dc..8e479c931b 100644 --- a/lib/wheel.c +++ b/lib/wheel.c @@ -80,7 +80,7 @@ static int wheel_timer_thread(struct thread *t) } struct timer_wheel *wheel_init(struct thread_master *master, int period, - size_t slots, unsigned int (*slot_key)(void *), + size_t slots, unsigned int (*slot_key)(const void *), void (*slot_run)(void *), const char *run_name) { diff --git a/lib/wheel.h b/lib/wheel.h index e66751c1d0..401789e1a0 100644 --- a/lib/wheel.h +++ b/lib/wheel.h @@ -38,7 +38,7 @@ struct timer_wheel { /* * Key to determine what slot the item belongs in */ - unsigned int (*slot_key)(void *); + unsigned int (*slot_key)(const void *); void (*slot_run)(void *); }; @@ -80,9 +80,9 @@ struct timer_wheel { * of running your code. */ struct timer_wheel *wheel_init(struct thread_master *master, int period, - size_t slots, unsigned int (*slot_key)(void *), - void (*slot_run)(void *), - const char *run_name); + size_t slots, + unsigned int (*slot_key)(const void *), + void (*slot_run)(void *), const char *run_name); /* * Delete the specified timer wheel created diff --git a/lib/yang_translator.c b/lib/yang_translator.c index 69fff5dbff..341420eeda 100644 --- a/lib/yang_translator.c +++ b/lib/yang_translator.c @@ -61,7 +61,7 @@ static bool yang_mapping_hash_cmp(const void *value1, const void *value2) return strmatch(c1->xpath_from_canonical, c2->xpath_from_canonical); } -static unsigned int yang_mapping_hash_key(void *value) +static unsigned int yang_mapping_hash_key(const void *value) { return string_hash_make(value); } diff --git a/lib/zebra.h b/lib/zebra.h index b1ea43c747..3e1eefdb2e 100644 --- a/lib/zebra.h +++ b/lib/zebra.h @@ -422,7 +422,13 @@ extern const char *zserv_command_string(unsigned int command); #endif /* Address family numbers from RFC1700. */ -typedef enum { AFI_IP = 1, AFI_IP6 = 2, AFI_L2VPN = 3, AFI_MAX = 4 } afi_t; +typedef enum { + AFI_UNSPEC = 0, + AFI_IP = 1, + AFI_IP6 = 2, + AFI_L2VPN = 3, + AFI_MAX = 4 +} afi_t; /* Subsequent Address Family Identifier. */ typedef enum { diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c index 5508778243..cc18b36f6a 100644 --- a/nhrpd/nhrp_cache.c +++ b/nhrpd/nhrp_cache.c @@ -30,9 +30,9 @@ const char *const nhrp_cache_type_str[] = { [NHRP_CACHE_LOCAL] = "local", }; -static unsigned int nhrp_cache_protocol_key(void *peer_data) +static unsigned int nhrp_cache_protocol_key(const void *peer_data) { - struct nhrp_cache *p = peer_data; + const struct nhrp_cache *p = peer_data; return sockunion_hash(&p->remote_addr); } diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c index db2f72ac22..ca309f2506 100644 --- a/nhrpd/nhrp_peer.c +++ b/nhrpd/nhrp_peer.c @@ -151,9 +151,9 @@ static void nhrp_peer_ifp_notify(struct notifier_block *n, unsigned long cmd) nhrp_peer_unref(p); } -static unsigned int nhrp_peer_key(void *peer_data) +static unsigned int nhrp_peer_key(const void *peer_data) { - struct nhrp_peer *p = peer_data; + const struct nhrp_peer *p = peer_data; return sockunion_hash(&p->vc->remote.nbma); } diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c index fa3549f5ed..605aa34ff9 100644 --- a/nhrpd/nhrp_vc.c +++ b/nhrpd/nhrp_vc.c @@ -28,9 +28,9 @@ struct child_sa { static struct hash *nhrp_vc_hash; static struct list_head childlist_head[512]; -static unsigned int nhrp_vc_key(void *peer_data) +static unsigned int nhrp_vc_key(const void *peer_data) { - struct nhrp_vc *vc = peer_data; + const struct nhrp_vc *vc = peer_data; return jhash_2words(sockunion_hash(&vc->local.nbma), sockunion_hash(&vc->remote.nbma), 0); } diff --git a/nhrpd/reqid.c b/nhrpd/reqid.c index 08a007bdf9..e56bbe3bf7 100644 --- a/nhrpd/reqid.c +++ b/nhrpd/reqid.c @@ -2,9 +2,9 @@ #include "hash.h" #include "nhrpd.h" -static unsigned int nhrp_reqid_key(void *data) +static unsigned int nhrp_reqid_key(const void *data) { - struct nhrp_reqid *r = data; + const struct nhrp_reqid *r = data; return r->request_id; } diff --git a/ospf6d/ospf6_bfd.c b/ospf6d/ospf6_bfd.c index 7a26af1f09..f0500601b0 100644 --- a/ospf6d/ospf6_bfd.c +++ b/ospf6d/ospf6_bfd.c @@ -74,6 +74,7 @@ void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command) struct interface *ifp = oi->interface; struct bfd_info *bfd_info; char src[64]; + int cbit; if (!oi->bfd_info || !on->bfd_info) return; @@ -85,9 +86,11 @@ void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command) bfd_get_command_dbg_str(command), src); } + cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); + bfd_peer_sendmsg(zclient, bfd_info, AF_INET6, &on->linklocal_addr, - on->ospf6_if->linklocal_addr, ifp->name, 0, 0, command, - 0, VRF_DEFAULT); + on->ospf6_if->linklocal_addr, ifp->name, 0, 0, + cbit, command, 0, VRF_DEFAULT); if (command == ZEBRA_BFD_DEST_DEREGISTER) bfd_info_free((struct bfd_info **)&on->bfd_info); @@ -195,7 +198,8 @@ static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS) struct bfd_info *bfd_info; struct timeval tv; - ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, vrf_id); + ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status, + NULL, vrf_id); if ((ifp == NULL) || (dp.family != AF_INET6)) return 0; diff --git a/ospfd/ospf_bfd.c b/ospfd/ospf_bfd.c index c8ad6d04f4..a17975270a 100644 --- a/ospfd/ospf_bfd.c +++ b/ospfd/ospf_bfd.c @@ -65,6 +65,7 @@ static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command) struct interface *ifp = oi->ifp; struct ospf_if_params *params; struct bfd_info *bfd_info; + int cbit; /* Check if BFD is enabled */ params = IF_DEF_PARAMS(ifp); @@ -80,8 +81,10 @@ static void ospf_bfd_reg_dereg_nbr(struct ospf_neighbor *nbr, int command) inet_ntoa(nbr->src), ospf_vrf_id_to_name(oi->ospf->vrf_id)); + cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); + bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->src, NULL, ifp->name, - 0, 0, command, 0, oi->ospf->vrf_id); + 0, 0, cbit, command, 0, oi->ospf->vrf_id); } /* @@ -207,7 +210,8 @@ static int ospf_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS) struct bfd_info *bfd_info; struct timeval tv; - ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, + NULL, vrf_id); if ((ifp == NULL) || (p.family != AF_INET)) return 0; diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c index a493520868..6947393a60 100644 --- a/ospfd/ospf_sr.c +++ b/ospfd/ospf_sr.c @@ -86,7 +86,7 @@ static inline void del_sid_nhlfe(struct sr_nhlfe nhlfe); */ /* Hash function for Segment Routing entry */ -static unsigned int sr_hash(void *p) +static unsigned int sr_hash(const void *p) { const struct in_addr *rid = p; diff --git a/pbrd/pbr_nht.c b/pbrd/pbr_nht.c index 7504752725..52506542bc 100644 --- a/pbrd/pbr_nht.c +++ b/pbrd/pbr_nht.c @@ -129,10 +129,10 @@ static void pbr_nh_delete_iterate(struct hash_bucket *b, void *p) pbr_nh_delete((struct pbr_nexthop_cache **)&b->data); } -static uint32_t pbr_nh_hash_key(void *arg) +static uint32_t pbr_nh_hash_key(const void *arg) { uint32_t key; - struct pbr_nexthop_cache *pbrnc = (struct pbr_nexthop_cache *)arg; + const struct pbr_nexthop_cache *pbrnc = arg; key = nexthop_hash(pbrnc->nexthop); @@ -789,10 +789,9 @@ void pbr_nht_nexthop_interface_update(struct interface *ifp) ifp); } -static uint32_t pbr_nhg_hash_key(void *arg) +static uint32_t pbr_nhg_hash_key(const void *arg) { - struct pbr_nexthop_group_cache *nhgc = - (struct pbr_nexthop_group_cache *)arg; + const struct pbr_nexthop_group_cache *nhgc = arg; return jhash(&nhgc->name, strlen(nhgc->name), 0x52c34a96); } @@ -940,7 +939,7 @@ void pbr_nht_init(void) pbr_nhg_hash = hash_create_size( 16, pbr_nhg_hash_key, pbr_nhg_hash_equal, "PBR NHG Cache Hash"); pbr_nhrc_hash = - hash_create_size(16, (unsigned int (*)(void *))nexthop_hash, + hash_create_size(16, (unsigned int (*)(const void *))nexthop_hash, pbr_nhrc_hash_equal, "PBR NH Hash"); pbr_nhg_low_table = PBR_NHT_DEFAULT_LOW_TABLEID; diff --git a/pbrd/pbr_zebra.c b/pbrd/pbr_zebra.c index aad0e4275f..466a9a13ae 100644 --- a/pbrd/pbr_zebra.c +++ b/pbrd/pbr_zebra.c @@ -349,6 +349,11 @@ void route_add(struct pbr_nexthop_group_cache *pnhgc, struct nexthop_group nhg, "%s: Asked to install unsupported route type: L2VPN", __PRETTY_FUNCTION__); break; + case AFI_UNSPEC: + DEBUGD(&pbr_dbg_zebra, + "%s: Asked to install unspecified route type", + __PRETTY_FUNCTION__); + break; } } @@ -391,6 +396,11 @@ void route_delete(struct pbr_nexthop_group_cache *pnhgc, afi_t afi) "%s: Asked to delete unsupported route type: L2VPN", __PRETTY_FUNCTION__); break; + case AFI_UNSPEC: + DEBUGD(&pbr_dbg_zebra, + "%s: Asked to delete unspecified route type", + __PRETTY_FUNCTION__); + break; } } diff --git a/pimd/pim_bfd.c b/pimd/pim_bfd.c index 300261e5a9..87d0f9fa22 100644 --- a/pimd/pim_bfd.c +++ b/pimd/pim_bfd.c @@ -111,6 +111,7 @@ static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command) struct pim_interface *pim_ifp = NULL; struct bfd_info *bfd_info = NULL; struct zclient *zclient = NULL; + int cbit; zclient = pim_zebra_zclient_get(); @@ -127,8 +128,12 @@ static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command) zlog_debug("%s Nbr %s %s with BFD", __PRETTY_FUNCTION__, str, bfd_get_command_dbg_str(command)); } + + cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON); + bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL, - nbr->interface->name, 0, 0, command, 0, VRF_DEFAULT); + nbr->interface->name, 0, 0, cbit, + command, 0, VRF_DEFAULT); } /* @@ -222,7 +227,8 @@ static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS) struct listnode *neigh_nextnode = NULL; struct pim_neighbor *neigh = NULL; - ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, vrf_id); + ifp = bfd_get_peer_info(zclient->ibuf, &p, NULL, &status, + NULL, vrf_id); if ((ifp == NULL) || (p.family != AF_INET)) return 0; diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c index 3a68176510..352177db2b 100644 --- a/pimd/pim_ifchannel.c +++ b/pimd/pim_ifchannel.c @@ -1425,9 +1425,9 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, pim_jp_agg_single_upstream_send(&starup->rpf, starup, true); } -unsigned int pim_ifchannel_hash_key(void *arg) +unsigned int pim_ifchannel_hash_key(const void *arg) { - struct pim_ifchannel *ch = (struct pim_ifchannel *)arg; + const struct pim_ifchannel *ch = arg; return jhash_2words(ch->sg.src.s_addr, ch->sg.grp.s_addr, 0); } diff --git a/pimd/pim_ifchannel.h b/pimd/pim_ifchannel.h index b9d4d291d8..b36c3236b0 100644 --- a/pimd/pim_ifchannel.h +++ b/pimd/pim_ifchannel.h @@ -155,5 +155,5 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom, int pim_ifchannel_compare(const struct pim_ifchannel *ch1, const struct pim_ifchannel *ch2); -unsigned int pim_ifchannel_hash_key(void *arg); +unsigned int pim_ifchannel_hash_key(const void *arg); #endif /* PIM_IFCHANNEL_H */ diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index cdd156b96f..213ca48bb5 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -829,9 +829,9 @@ void igmp_sock_delete_all(struct interface *ifp) } } -static unsigned int igmp_group_hash_key(void *arg) +static unsigned int igmp_group_hash_key(const void *arg) { - struct igmp_group *group = (struct igmp_group *)arg; + const struct igmp_group *group = arg; return jhash_1word(group->group_addr.s_addr, 0); } diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c index 395c4af35f..3287e13719 100644 --- a/pimd/pim_msdp.c +++ b/pimd/pim_msdp.c @@ -680,9 +680,9 @@ void pim_msdp_up_del(struct pim_instance *pim, struct prefix_sg *sg) } /* sa hash and peer list helpers */ -static unsigned int pim_msdp_sa_hash_key_make(void *p) +static unsigned int pim_msdp_sa_hash_key_make(const void *p) { - struct pim_msdp_sa *sa = p; + const struct pim_msdp_sa *sa = p; return (jhash_2words(sa->sg.src.s_addr, sa->sg.grp.s_addr, 0)); } @@ -1215,9 +1215,9 @@ enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim, } /* peer hash and peer list helpers */ -static unsigned int pim_msdp_peer_hash_key_make(void *p) +static unsigned int pim_msdp_peer_hash_key_make(const void *p) { - struct pim_msdp_peer *mp = p; + const struct pim_msdp_peer *mp = p; return (jhash_1word(mp->peer.s_addr, 0)); } diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 5945bc55fd..22045c2d33 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -91,9 +91,9 @@ static bool pim_oil_equal(const void *arg1, const void *arg2) return false; } -static unsigned int pim_oil_hash_key(void *arg) +static unsigned int pim_oil_hash_key(const void *arg) { - struct channel_oil *oil = (struct channel_oil *)arg; + const struct channel_oil *oil = arg; return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr, oil->oil.mfcc_origin.s_addr, 0); diff --git a/pimd/pim_rpf.c b/pimd/pim_rpf.c index afe3886aa5..dba46e63f0 100644 --- a/pimd/pim_rpf.c +++ b/pimd/pim_rpf.c @@ -426,9 +426,9 @@ int pim_rpf_is_same(struct pim_rpf *rpf1, struct pim_rpf *rpf2) return 0; } -unsigned int pim_rpf_hash_key(void *arg) +unsigned int pim_rpf_hash_key(const void *arg) { - struct pim_nexthop_cache *r = (struct pim_nexthop_cache *)arg; + const struct pim_nexthop_cache *r = arg; return jhash_1word(r->rpf.rpf_addr.u.prefix4.s_addr, 0); } diff --git a/pimd/pim_rpf.h b/pimd/pim_rpf.h index 57bb22674f..1172acb4b2 100644 --- a/pimd/pim_rpf.h +++ b/pimd/pim_rpf.h @@ -56,7 +56,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); +unsigned int pim_rpf_hash_key(const void *arg); bool pim_rpf_equal(const void *arg1, const void *arg2); bool pim_nexthop_lookup(struct pim_instance *pim, struct pim_nexthop *nexthop, diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index d829d01347..55d998f270 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -1629,9 +1629,9 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim) } } -unsigned int pim_upstream_hash_key(void *arg) +unsigned int pim_upstream_hash_key(const void *arg) { - struct pim_upstream *up = (struct pim_upstream *)arg; + const struct pim_upstream *up = arg; return jhash_2words(up->sg.src.s_addr, up->sg.grp.s_addr, 0); } diff --git a/pimd/pim_upstream.h b/pimd/pim_upstream.h index 13a3dcdf8c..102826ac71 100644 --- a/pimd/pim_upstream.h +++ b/pimd/pim_upstream.h @@ -308,7 +308,7 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim, void pim_upstream_spt_prefix_list_update(struct pim_instance *pim, struct prefix_list *pl); -unsigned int pim_upstream_hash_key(void *arg); +unsigned int pim_upstream_hash_key(const void *arg); bool pim_upstream_equal(const void *arg1, const void *arg2); struct pim_upstream *pim_upstream_keep_alive_timer_proc( struct pim_upstream *up); diff --git a/pimd/pim_vxlan.c b/pimd/pim_vxlan.c index af76c6d732..1c6b56568f 100644 --- a/pimd/pim_vxlan.c +++ b/pimd/pim_vxlan.c @@ -623,9 +623,9 @@ static void pim_vxlan_term_mr_del(struct pim_vxlan_sg *vxlan_sg) } /************************** vxlan SG cache management ************************/ -static unsigned int pim_vxlan_sg_hash_key_make(void *p) +static unsigned int pim_vxlan_sg_hash_key_make(const void *p) { - struct pim_vxlan_sg *vxlan_sg = p; + const struct pim_vxlan_sg *vxlan_sg = p; return (jhash_2words(vxlan_sg->sg.src.s_addr, vxlan_sg->sg.grp.s_addr, 0)); diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c index c03a371d88..c6da00418b 100644 --- a/staticd/static_zebra.c +++ b/staticd/static_zebra.c @@ -223,9 +223,9 @@ static void static_zebra_capabilities(struct zclient_capabilities *cap) mpls_enabled = cap->mpls_enabled; } -static unsigned int static_nht_hash_key(void *data) +static unsigned int static_nht_hash_key(const void *data) { - struct static_nht_data *nhtd = data; + const struct static_nht_data *nhtd = data; unsigned int key = 0; key = prefix_hash_key(nhtd->nh); diff --git a/tests/lib/test_srcdest_table.c b/tests/lib/test_srcdest_table.c index 19a40b2184..0fca571d28 100644 --- a/tests/lib/test_srcdest_table.c +++ b/tests/lib/test_srcdest_table.c @@ -81,9 +81,9 @@ static char *format_srcdest(const struct prefix_ipv6 *dst_p, return rv; } -static unsigned int log_key(void *data) +static unsigned int log_key(const void *data) { - struct prefix *hash_entry = data; + const struct prefix *hash_entry = data; struct prefix_ipv6 *dst_p = (struct prefix_ipv6 *)&hash_entry[0]; struct prefix_ipv6 *src_p = (struct prefix_ipv6 *)&hash_entry[1]; unsigned int hash = 0; diff --git a/tests/topotests/bfd-bgp-cbit-topo3/__init__.py b/tests/topotests/bfd-bgp-cbit-topo3/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/__init__.py diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json new file mode 100644 index 0000000000..54ae57f7be --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgp_ipv6_routes_down.json @@ -0,0 +1,103 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "10.254.254.1", + "localAS": 101, + "routes": + { + "2001:db8:6::/64": [ + { + "stale": true, + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:6::", + "prefixLen": 64, + "network": "2001:db8:6::\/64", + "med": 0, + "metric": 0, + "weight": 0, + "peerId": "2001:db8:4::1", + "origin": "IGP", + "nexthops": [ + { "ip": "2001:db8:4::1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8:7::/64": [ + { + "stale": true, + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:7::", + "prefixLen": 64, "network": + "2001:db8:7::\/64", + "med": 0, + "metric": 0, + "weight": 0, + "peerId": "2001:db8:4::1", + "origin": "IGP", + "nexthops": [ + { + "ip": "2001:db8:4::1", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8:8::/64": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:8::", + "prefixLen": 64, + "network": "2001:db8:8::\/64", + "med": 0, + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "origin": "IGP", + "nexthops": [ + { + "ip": "::", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8:9::/64": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:9::", + "prefixLen": 64, + "network": "2001:db8:9::\/64", + "med": 0, + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "origin": "IGP", + "nexthops": [ + { + "ip": "::", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} + diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf new file mode 100644 index 0000000000..fa6d60a8fc --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/bgpd.conf @@ -0,0 +1,20 @@ +debug bgp neighbor-events +router bgp 101 + bgp router-id 10.254.254.1 + timers bgp 8 24 + bgp graceful-restart + neighbor 2001:db8:4::1 remote-as 102 + neighbor 2001:db8:4::1 remote-as external + neighbor 2001:db8:4::1 bfd + neighbor 2001:db8:4::1 bfd check-control-plane-failure + neighbor 2001:db8:4::1 update-source 2001:db8:1::1 + neighbor 2001:db8:4::1 ebgp-multihop 5 + address-family ipv4 unicast + no neighbor 2001:db8:4::1 activate + exit-address-family + address-family ipv6 unicast + network 2001:db8:8::/64 + network 2001:db8:9::/64 + neighbor 2001:db8:4::1 activate + exit-address-family +! diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json new file mode 100644 index 0000000000..8eea183285 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/ipv6_routes.json @@ -0,0 +1,80 @@ +{ + "2001:db8:1::/64": [{ + "distance": 0, + "protocol": "connected", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:1::/64", + "nexthops": [{ + "directlyConnected": true, + "interfaceName": "r1-eth0", + "fib": true, + "flags": 3, + "active": true + } + ] + } + ], + "2001:db8:4::/64": [{ + "distance": 1, + "protocol": "static", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:4::/64", + "nexthops": [{ + "interfaceName": "r1-eth0", + "fib": true, + "flags": 3, + "active": true, + "afi": "ipv6" + } + ] + } + ], + "2001:db8:6::/64": [{ + "distance": 20, + "protocol": "bgp", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:6::/64", + "nexthops": [{ + "ip":"2001:db8:4::1", + "active": true, + "afi": "ipv6", + "recursive":true + }, + { + "fib":true, + "ip":"2001:db8:1::2", + "afi": "ipv6", + "interfaceName": "r1-eth0" + } + ] + } + ], + "2001:db8:7::/64": [{ + "distance": 20, + "protocol": "bgp", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:7::/64", + "nexthops": [{ + "ip":"2001:db8:4::1", + "active": true, + "afi": "ipv6", + "recursive": true + }, + { + "fib":true, + "ip":"2001:db8:1::2", + "afi": "ipv6", + "interfaceName":"r1-eth0" + } + ] + } + ] +} diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json new file mode 100644 index 0000000000..d1927ae49a --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers.json @@ -0,0 +1,16 @@ +[ + { + "multihop":true, + "peer":"2001:db8:4::1", + "local":"2001:db8:1::1", + "status":"up", + "diagnostic":"ok", + "remote-diagnostic":"ok", + "receive-interval":300, + "transmit-interval":300, + "echo-interval":0, + "remote-receive-interval":300, + "remote-transmit-interval":300, + "remote-echo-interval":50 + } +] diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json new file mode 100644 index 0000000000..25b47f18ec --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json @@ -0,0 +1,14 @@ +[ + { + "multihop":true, + "peer":"2001:db8:4::1", + "local":"2001:db8:1::1", + "status":"up", + "receive-interval":300, + "transmit-interval":300, + "echo-interval":0, + "remote-receive-interval":300, + "remote-transmit-interval":300, + "remote-echo-interval":50 + } +] diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf new file mode 100644 index 0000000000..3a30cd42fb --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r1/zebra.conf @@ -0,0 +1,8 @@ +interface lo + ip address 10.254.254.1/32 +! +interface r1-eth0 + ipv6 address 2001:db8:1::1/64 +! +ipv6 route 2001:db8:4::/64 2001:db8:1::2 + diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf new file mode 100644 index 0000000000..0f70be1bda --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r2/zebra.conf @@ -0,0 +1,9 @@ +ip forwarding +ipv6 forwarding +! +interface r2-eth0 + ipv6 address 2001:db8:1::2/64 +! +interface r2-eth1 + ipv6 address 2001:db8:4::2/64 +! diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json new file mode 100644 index 0000000000..a3bb222504 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgp_ipv6_routes_down.json @@ -0,0 +1,55 @@ +{ + "vrfId": 0, + "vrfName": "default", + "routerId": "10.254.254.3", + "localAS": 102, + "routes": + { + "2001:db8:6::/64": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:6::", + "prefixLen": 64, + "network": "2001:db8:6::\/64", + "med": 0, + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "origin": "IGP", + "nexthops": [ + { + "ip": "::", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ], + "2001:db8:7::/64": [ + { + "valid": true, + "bestpath": true, + "pathFrom": "external", + "prefix": "2001:db8:7::", + "prefixLen": 64, + "network": "2001:db8:7::\/64", + "med": 0, + "metric": 0, + "weight": 32768, + "peerId": "(unspec)", + "origin": "IGP", + "nexthops": [ + { + "ip": "::", + "afi": "ipv6", + "scope": "global", + "used": true + } + ] + } + ] + } +} diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf new file mode 100644 index 0000000000..ea5334029c --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/bgpd.conf @@ -0,0 +1,25 @@ +debug bgp neighbor-events +router bgp 102 + bgp router-id 10.254.254.3 + timers bgp 20 60 + bgp graceful-restart + ! simulate NSF machine + bgp graceful-restart preserve-fw-state + bgp graceful-restart stalepath-time 900 + bgp graceful-restart restart-time 900 + neighbor 2001:db8:1::1 remote-as 101 + neighbor 2001:db8:1::1 remote-as external + neighbor 2001:db8:1::1 update-source 2001:db8:4::1 + neighbor 2001:db8:1::1 bfd + neighbor 2001:db8:1::1 ebgp-multihop 5 + ! + address-family ipv4 unicast + no neighbor 2001:db8:1::1 activate + exit-address-family + ! + address-family ipv6 unicast + neighbor 2001:db8:1::1 activate + network 2001:db8:6::/64 + network 2001:db8:7::/64 + exit-address-family +! diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json new file mode 100644 index 0000000000..09808cc09a --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/ipv6_routes.json @@ -0,0 +1,80 @@ +{ + "2001:db8:1::/64": [{ + "distance": 1, + "protocol": "static", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:1::/64", + "nexthops": [{ + "interfaceName": "r3-eth0", + "fib": true, + "flags": 3, + "active": true, + "afi": "ipv6" + } + ] + } + ], + "2001:db8:4::/64": [{ + "distance": 0, + "protocol": "connected", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:4::/64", + "nexthops": [{ + "directlyConnected": true, + "interfaceName": "r3-eth0", + "fib": true, + "flags": 3, + "active": true + } + ] + } + ], + "2001:db8:8::/64": [{ + "distance": 20, + "protocol": "bgp", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:8::/64", + "nexthops": [{ + "ip":"2001:db8:1::1", + "active": true, + "afi": "ipv6", + "recursive":true + }, + { + "fib":true, + "ip":"2001:db8:4::2", + "afi": "ipv6", + "interfaceName":"r3-eth0" + } + ] + } + ], + "2001:db8:9::/64": [{ + "distance": 20, + "protocol": "bgp", + "metric": 0, + "selected": true, + "destSelected": true, + "prefix": "2001:db8:9::/64", + "nexthops": [{ + "ip":"2001:db8:1::1", + "active": true, + "afi": "ipv6", + "recursive":true + }, + { + "fib":true, + "ip":"2001:db8:4::2", + "afi": "ipv6", + "interfaceName":"r3-eth0" + } + ] + } + ] +} diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json new file mode 100644 index 0000000000..5193f2a6e2 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers.json @@ -0,0 +1,16 @@ +[ + { + "multihop":true, + "peer":"2001:db8:1::1", + "local":"2001:db8:4::1", + "status":"up", + "diagnostic":"ok", + "remote-diagnostic":"ok", + "receive-interval":300, + "transmit-interval":300, + "echo-interval":0, + "remote-receive-interval":300, + "remote-transmit-interval":300, + "remote-echo-interval":50 + } +] diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json new file mode 100644 index 0000000000..9e4bd2633f --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/peers_down.json @@ -0,0 +1,14 @@ +[ + { + "multihop":true, + "peer":"2001:db8:1::1", + "local":"2001:db8:4::1", + "status":"down", + "receive-interval":300, + "transmit-interval":300, + "echo-interval":0, + "remote-receive-interval":300, + "remote-transmit-interval":300, + "remote-echo-interval":50 + } +] diff --git a/tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf b/tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf new file mode 100644 index 0000000000..7759251dc5 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/r3/zebra.conf @@ -0,0 +1,7 @@ +interface lo + ip address 10.254.254.3/32 +! +interface r3-eth0 + ipv6 address 2001:db8:4::1/64 +! +ipv6 route 2001:db8:1::/64 2001:db8:4::2 diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot new file mode 100644 index 0000000000..270de829c3 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.dot @@ -0,0 +1,58 @@ +## Color coding: +######################### +## Main FRR: #f08080 red +## Switches: #d0e0d0 gray +## RIP: #19e3d9 Cyan +## RIPng: #fcb314 dark yellow +## OSPFv2: #32b835 Green +## OSPFv3: #19e3d9 Cyan +## ISIS IPv4 #fcb314 dark yellow +## ISIS IPv6 #9a81ec purple +## BGP IPv4 #eee3d3 beige +## BGP IPv6 #fdff00 yellow +##### Colors (see http://www.color-hex.com/) + +graph template { + label="bfd-topo2"; + + # Routers + r1 [ + shape=doubleoctagon, + label="r1", + fillcolor="#f08080", + style=filled, + ]; + r2 [ + shape=doubleoctagon + label="r2", + fillcolor="#f08080", + style=filled, + ]; + r3 [ + shape=doubleoctagon + label="r4", + fillcolor="#f08080", + style=filled, + ]; + + # Switches + sw1 [ + shape=oval, + label="sw1\n2001:db8:1::/64", + fillcolor="#d0e0d0", + style=filled, + ]; + sw2 [ + shape=oval, + label="sw2\n10.0.3.0/24", + fillcolor="#d0e0d0", + style=filled, + ]; + + # Connections + r1 -- sw1 [label="eth0"]; + r2 -- sw1 [label="eth0"]; + + r2 -- sw2 [label="eth1"]; + r3 -- sw2 [label="eth0"]; +} diff --git a/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py new file mode 100755 index 0000000000..59858d6fd3 --- /dev/null +++ b/tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python + +# +# test_bfd_bgp_cbit_topo3.py +# +# Copyright (c) 2019 6WIND +# +# Permission to use, copy, modify, and/or distribute this software +# for any purpose with or without fee is hereby granted, provided +# that the above copyright notice and this permission notice appear +# in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY +# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +# OF THIS SOFTWARE. +# + +""" +test_bfd_bgp_cbit_topo3.py: Test the FRR/Quagga BFD daemon with multihop and BGP +unnumbered. +""" + +import os +import sys +import json +from functools import partial +import pytest + +# Save the Current Working Directory to find configuration files. +CWD = os.path.dirname(os.path.realpath(__file__)) +sys.path.append(os.path.join(CWD, '../')) + +# pylint: disable=C0413 +# Import topogen and topotest helpers +from lib import topotest +from lib.topogen import Topogen, TopoRouter, get_topogen +from lib.topolog import logger + +# Required to instantiate the topology builder class. +from mininet.topo import Topo + +class BFDTopo(Topo): + "Test topology builder" + def build(self, *_args, **_opts): + "Build function" + tgen = get_topogen(self) + + # Create 4 routers. + for routern in range(1, 4): + tgen.add_router('r{}'.format(routern)) + + switch = tgen.add_switch('s1') + switch.add_link(tgen.gears['r1']) + switch.add_link(tgen.gears['r2']) + + switch = tgen.add_switch('s2') + switch.add_link(tgen.gears['r2']) + switch.add_link(tgen.gears['r3']) + +def setup_module(mod): + "Sets up the pytest environment" + tgen = Topogen(BFDTopo, mod.__name__) + tgen.start_topology() + + router_list = tgen.routers() + + for rname, router in router_list.iteritems(): + router.load_config( + TopoRouter.RD_ZEBRA, + os.path.join(CWD, '{}/zebra.conf'.format(rname)), + ) + router.load_config( + TopoRouter.RD_BFD, + os.path.join(CWD, '{}/bfdd.conf'.format(rname)) + ) + router.load_config( + TopoRouter.RD_BGP, + os.path.join(CWD, '{}/bgpd.conf'.format(rname)) + ) + + # Initialize all routers. + tgen.start_router() + + # Verify that we are using the proper version and that the BFD + # daemon exists. + for router in router_list.values(): + # Check for Version + if router.has_version('<', '5.1'): + tgen.set_error('Unsupported FRR version') + break + +def teardown_module(_mod): + "Teardown the pytest environment" + tgen = get_topogen() + tgen.stop_topology() + + +def test_protocols_convergence(): + """ + Assert that all protocols have converged before checking for the BFD + statuses as they depend on it. + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + # Check IPv6 routing tables. + logger.info("Checking IPv6 routes for convergence") + for router in tgen.routers().values(): + if router.name == 'r2': + continue + json_file = '{}/{}/ipv6_routes.json'.format(CWD, router.name) + if not os.path.isfile(json_file): + logger.info('skipping file {}'.format(json_file)) + continue + expected = json.loads(open(json_file).read()) + test_func = partial(topotest.router_json_cmp, + router, 'show ipv6 route json', expected) + _, result = topotest.run_and_expect(test_func, None, count=40, + wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +def test_bfd_connection(): + "Assert that the BFD peers can find themselves." + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info('waiting for bfd peers to go up') + for router in tgen.routers().values(): + if router.name == 'r2': + continue + json_file = '{}/{}/peers.json'.format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial(topotest.router_json_cmp, + router, 'show bfd peers json', expected) + _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + +def test_bfd_loss_intermediate(): + """ + Assert that BFD notices the bfd link down failure. + but BGP entries should still be present + """ + tgen = get_topogen() + if tgen.routers_have_failure(): + pytest.skip(tgen.errors) + + logger.info('removing IPv6 address from r2 to simulate loss of connectivity') + # Disable r2-eth0 ipv6 address + cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "no ipv6 address 2001:db8:4::2/64\"' + tgen.net['r2'].cmd(cmd) + + # Wait the minimum time we can before checking that BGP/BFD + # converged. + logger.info('waiting for BFD converge down') + + # Check that BGP converged quickly. + for router in tgen.routers().values(): + if router.name == 'r2': + continue + json_file = '{}/{}/peers_down.json'.format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial(topotest.router_json_cmp, + router, 'show bfd peers json', expected) + _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + logger.info('waiting for BGP entries to become stale') + for router in tgen.routers().values(): + if router.name == 'r2': + continue + json_file = '{}/{}/bgp_ipv6_routes_down.json'.format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial(topotest.router_json_cmp, + router, 'show bgp ipv6 json', expected) + _, result = topotest.run_and_expect(test_func, None, count=50, wait=1) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + logger.info("Checking IPv6 routes on r1 should still be present") + for router in tgen.routers().values(): + if router.name == 'r2': + continue + if router.name == 'r3': + continue + json_file = '{}/r1/ipv6_routes.json'.format(CWD) + expected = json.loads(open(json_file).read()) + test_func = partial(topotest.router_json_cmp, + router, 'show ipv6 route json', expected) + _, result = topotest.run_and_expect(test_func, None, count=30, + wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + +def test_bfd_comes_back_again(): + """ + Assert that BFD notices the bfd link up + and that ipv6 entries appear back + """ + tgen = get_topogen() + logger.info('re-adding IPv6 address from r2 to simulate connectivity is back') + # adds back r2-eth0 ipv6 address + cmd = 'vtysh -c \"configure terminal\" -c \"interface r2-eth1\" -c "ipv6 address 2001:db8:4::2/64\"' + tgen.net['r2'].cmd(cmd) + + # Wait the minimum time we can before checking that BGP/BFD + # converged. + logger.info('waiting for BFD to converge up') + + # Check that BGP converged quickly. + for router in tgen.routers().values(): + if router.name == 'r2': + continue + json_file = '{}/{}/peers.json'.format(CWD, router.name) + expected = json.loads(open(json_file).read()) + + test_func = partial(topotest.router_json_cmp, + router, 'show bfd peers json', expected) + _, result = topotest.run_and_expect(test_func, None, count=8, wait=0.5) + assertmsg = '"{}" JSON output mismatches'.format(router.name) + assert result is None, assertmsg + + +def test_memory_leak(): + "Run the memory leak test and report results." + tgen = get_topogen() + if not tgen.is_memleak_enabled(): + pytest.skip('Memory leak test/report is disabled') + + tgen.report_memory_leaks() + + +if __name__ == '__main__': + args = ["-s"] + sys.argv[1:] + sys.exit(pytest.main(args)) diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf index 4bd0f95f2c..a38fb1e9a1 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/bgpd.conf @@ -15,6 +15,7 @@ router bgp 5227 network 99.0.0.1/32 network 5.1.0.0/24 route-map rm-nh network 5.1.1.0/24 route-map rm-nh + redistribute sharp route-map sharp-nh neighbor 192.168.1.1 activate exit-address-family ! @@ -29,6 +30,15 @@ route-map rm-nh permit 10 set extcommunity rt 89:123 set community 0:67 ! +route-map sharp-nh permit 10 + match ip address al-any + set ip next-hop 99.0.0.1 + set local-preference 200 + set metric 200 + set large-community 90:12:34 + set extcommunity rt 80:987 + set community 0:65 +! end diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce1/sharpd.conf diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf index 2115f08741..3aeb9f9c9f 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/bgpd.conf @@ -15,6 +15,7 @@ router bgp 5227 network 99.0.0.2/32 network 5.1.0.0/24 route-map rm-nh network 5.1.1.0/24 route-map rm-nh + redistribute sharp route-map sharp-nh neighbor 192.168.1.1 activate exit-address-family ! @@ -29,6 +30,15 @@ route-map rm-nh permit 10 set extcommunity rt 89:123 set community 0:67 ! +route-map sharp-nh permit 10 + match ip address al-any + set ip next-hop 99.0.0.2 + set local-preference 200 + set metric 200 + set large-community 78:90:12 + set extcommunity rt 70:456 + set community 0:66 +! end diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/ce2/sharpd.conf diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf index 2004612557..c4b6ac9bb4 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r3/bgpd.conf @@ -7,7 +7,7 @@ log monitor notifications log commands log file bgpd.log -debug bgp vpn label +#debug bgp vpn label router bgp 5226 bgp router-id 3.3.3.3 bgp cluster-id 3.3.3.3 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf index b2df5990ce..6295406e69 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/r4/bgpd.conf @@ -7,9 +7,9 @@ log monitor notifications log commands log file bgpd.log debug -debug bgp vpn label -debug bgp nht -debug bgp zebra +#debug bgp vpn label +#debug bgp nht +#debug bgp zebra router bgp 5226 bgp router-id 4.4.4.4 diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py index f5d73a8c49..149a420a32 100644 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_linux_vrf.py @@ -1,5 +1,6 @@ from lutil import luCommand from customize import l3mdev_accept + l3mdev_rtrs = ['r1', 'r3', 'r4', 'ce4'] for rtr in l3mdev_rtrs: luCommand(rtr,'sysctl net.ipv4.tcp_l3mdev_accept',' = \d*','none','') diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py new file mode 100644 index 0000000000..897fc48436 --- /dev/null +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_down.py @@ -0,0 +1,20 @@ +from lutil import luCommand +ret = luCommand('ce1', 'vtysh -c "show ip route" | grep -c \\ 10\\.\\*/32','(.*)','pass', 'Looking for sharp routes') +found = luLast() +if ret != False and found != None: + num = int(found.group()) + luCommand('ce3', 'vtysh -c "show bgp sum"', + '.', 'pass', 'See %s sharp routes' % num) + if num > 0: + wait = num/500 + luCommand('ce1', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num)) + luCommand('ce2', 'vtysh -c "sharp remove routes 10.0.0.0 {}"'.format(num),'.','none','Removing {} routes'.format(num)) + rtrs = ['ce1', 'ce2', 'ce3'] + for rtr in rtrs: + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32','^0$', 'wait', 'BGP routes removed', wait) + for rtr in rtrs: + luCommand(rtr, 'ip route show | grep -c \\^10\\.','^0$', 'wait', 'Linux routes removed', wait) + rtrs = ['r1', 'r3', 'r4'] + for rtr in rtrs: + luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr),'^0$','wait','VRF route removed',wait) +#done diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py new file mode 100644 index 0000000000..3b3aac5fbe --- /dev/null +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py @@ -0,0 +1,66 @@ +from lutil import luCommand +num = 50000 +b = int(num/(256*256)) +if b > 0: + r = num - b * (256*256) +else: + r = num +c = int(r/256) +if c > 0: + d = r - c * 256 - 1 +else: + d = r +wait = num/1000 +mem = {} +rtrs = ['ce1', 'ce2', 'ce3', 'r1', 'r2', 'r3', 'r4'] +for rtr in rtrs: + mem[rtr] = {'value': 0, 'units': 'unknown'} + ret = luCommand(rtr, 'vtysh -c "show memory"', 'bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)', 'none', 'collect bgpd memory stats') + found = luLast() + if ret != False and found != None: + mem[rtr] = {'value': int(found.group(1)), 'units': found.group(2)} + +luCommand('ce1', 'vtysh -c "sharp data nexthop"', 'sharpd is not running', 'none','check if sharpd running') +doSharp = True +found = luLast() +if ret != False and found != None: + if len(found.group()): + luCommand('ce1', 'vtysh -c "sharp data nexthop"', 'sharpd is not running', 'pass','sharpd NOT running, skipping test') + doSharp = False + +if doSharp == True: + luCommand('ce1', 'vtysh -c "sharp install routes 10.0.0.0 nexthop 99.0.0.1 {}"'.format(num),'','pass','Adding {} routes'.format(num)) + luCommand('ce2', 'vtysh -c "sharp install routes 10.0.0.0 nexthop 99.0.0.2 {}"'.format(num),'','pass','Adding {} routes'.format(num)) + rtrs = ['ce1', 'ce2', 'ce3'] + for rtr in rtrs: + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni 10.{}.{}.{}"'.format(b,c,d), 'Last update:', 'wait', 'RXed last route, 10.{}.{}.{}'.format(b,c,d), wait) + luCommand(rtr, 'vtysh -c "show bgp ipv4 uni" | grep -c 10\\.\\*/32', str(num), 'wait', 'See all sharp routes in BGP', wait) + luCommand('r1', 'vtysh -c "show bgp vrf r1-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','RXed -> 10.{}.{}.{} from CE1'.format(b,c,d), wait) + luCommand('r3', 'vtysh -c "show bgp vrf r3-cust1 ipv4 uni 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','RXed -> 10.{}.{}.{} from CE2'.format(b,c,d), wait) + luCommand('r1', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d)) + luCommand('r3', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'99.0.0.2','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d)) + luCommand('r3', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'1.1.1.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d)) + luCommand('r1', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'3.3.3.3','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d)) + luCommand('r4', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'1.1.1.1','wait','see VPN safi -> 10.{}.{}.{} from CE1'.format(b,c,d)) + luCommand('r4', 'vtysh -c "show bgp ipv4 vpn 10.{}.{}.{}"'.format(b,c,d),'3.3.3.3','wait','see VPN safi -> 10.{}.{}.{} from CE2'.format(b,c,d)) + rtrs = ['ce1', 'ce2', 'ce3'] + for rtr in rtrs: + luCommand(rtr, 'ip route get 10.{}.{}.{}'.format(b,c,d),'dev','wait','Route to 10.{}.{}.{} available'.format(b,c,d), wait) + luCommand(rtr, 'ip route show | grep -c \\^10\\.', str(num), 'wait', 'See {} linux routes'.format(num), wait) + + rtrs = ['r1', 'r3', 'r4'] + for rtr in rtrs: + luCommand(rtr, 'ip route get vrf {}-cust1 10.{}.{}.{}'.format(rtr,b,c,d),'dev','wait','VRF route available',wait) + luCommand(rtr, 'ip route show vrf {}-cust1 | grep -c \\^10\\.'.format(rtr), str(num), 'wait','See {} linux routes'.format(num), wait) + rtrs = ['ce1', 'ce2', 'ce3', 'r1', 'r2', 'r3', 'r4'] + for rtr in rtrs: + ret = luCommand(rtr, 'vtysh -c "show memory"', 'bgpd: System allocator statistics: Total heap allocated: *(\d*) ([A-Za-z]*)', 'none', 'collect bgpd memory stats') + found = luLast() + if ret != False and found != None: + val = int(found.group(1)) + if mem[rtr]['units'] != found.group(2): + val *= 1000 + delta = val - int(mem[rtr]['value']) + ave = float(delta)/float(num) + luCommand(rtr, 'vtysh -c "show thread cpu"', '.', 'pass', 'BGPd heap: {0} {1} --> {2} {3} ({4} {1}/route)'.format(mem[rtr]['value'], mem[rtr]['units'], found.group(1), found.group(2), round(ave,4))) +#done diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py index 1da1066f0e..2dad5e7687 100755 --- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py +++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py @@ -75,6 +75,24 @@ def test_check_linux_mpls(): #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')' ltemplateTest('scripts/check_linux_mpls.py', False, CliOnFail, CheckFunc) +def test_check_scale_up(): + CliOnFail = None + # For debugging, uncomment the next line + #CliOnFail = 'tgen.mininet_cli' + CheckFunc = 'ltemplateVersionCheck(\'4.1\', iproute2=\'4.9\')' + #uncomment next line to start cli *before* script is run + #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')' + ltemplateTest('scripts/scale_up.py', False, CliOnFail, CheckFunc) + +def test_check_scale_down(): + CliOnFail = None + # For debugging, uncomment the next line + #CliOnFail = 'tgen.mininet_cli' + CheckFunc = 'ltemplateVersionCheck(\'4.1\', iproute2=\'4.9\')' + #uncomment next line to start cli *before* script is run + #CheckFunc = 'ltemplateVersionCheck(\'4.1\', cli=True, iproute2=\'4.9\')' + ltemplateTest('scripts/scale_down.py', False, CliOnFail, CheckFunc) + def SKIP_test_cleanup_all(): CliOnFail = None # For debugging, uncomment the next line diff --git a/tests/topotests/lib/ltemplate.py b/tests/topotests/lib/ltemplate.py index 31eaec7009..1d12d11a26 100644 --- a/tests/topotests/lib/ltemplate.py +++ b/tests/topotests/lib/ltemplate.py @@ -83,22 +83,15 @@ class LTemplate(): # For all registred routers, load the zebra configuration file for rname, router in router_list.iteritems(): - print("Setting up %s" % rname) - config = os.path.join(self.testdir, '{}/zebra.conf'.format(rname)) - if os.path.exists(config): - router.load_config(TopoRouter.RD_ZEBRA, config) - config = os.path.join(self.testdir, '{}/ospfd.conf'.format(rname)) - if os.path.exists(config): - router.load_config(TopoRouter.RD_OSPF, config) - config = os.path.join(self.testdir, '{}/ldpd.conf'.format(rname)) - if os.path.exists(config): - router.load_config(TopoRouter.RD_LDP, config) - config = os.path.join(self.testdir, '{}/bgpd.conf'.format(rname)) - if os.path.exists(config): - router.load_config(TopoRouter.RD_BGP, config) - config = os.path.join(self.testdir, '{}/isisd.conf'.format(rname)) - if os.path.exists(config): - router.load_config(TopoRouter.RD_ISIS, config) + logger.info("Setting up %s" % rname) + for rd_val in TopoRouter.RD: + config = os.path.join(self.testdir, '{}/{}.conf'.format(rname,TopoRouter.RD[rd_val])) + prog = os.path.join(tgen.net[rname].daemondir, TopoRouter.RD[rd_val]) + if os.path.exists(config): + if os.path.exists(prog): + router.load_config(rd_val, config) + else: + logger.warning("{} not found, but have {}.conf file".format(prog, TopoRouter.RD[rd_val])) # After loading the configurations, this function loads configured daemons. logger.info('Starting routers') diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py index 0bc1596eb2..d7145c3be0 100644 --- a/tests/topotests/lib/topogen.py +++ b/tests/topotests/lib/topogen.py @@ -540,6 +540,7 @@ class TopoRouter(TopoGear): RD_NHRP = 11 RD_STATIC = 12 RD_BFD = 13 + RD_SHARP = 14 RD = { RD_ZEBRA: 'zebra', RD_RIP: 'ripd', @@ -554,6 +555,7 @@ class TopoRouter(TopoGear): RD_NHRP: 'nhrpd', RD_STATIC: 'staticd', RD_BFD: 'bfdd', + RD_SHARP: 'sharpd', } def __init__(self, tgen, cls, name, **params): diff --git a/tools/coccinelle/hash_const.cocci b/tools/coccinelle/hash_const.cocci new file mode 100644 index 0000000000..9c53cb01fb --- /dev/null +++ b/tools/coccinelle/hash_const.cocci @@ -0,0 +1,76 @@ +// +// Transition hash key signatures to take their argument as const. +// Does not handle headers or weirdly named hash functions. +// +@noconst disable optional_qualifier@ +identifier A; +identifier func =~ ".*key$|.*key_make$|.*hash_make$|.*hash_keymake$|.*hash_key$|.*hash_key.*"; +@@ + +- func (void *A) ++ func (const void *A) + { ... } + +@ depends on noconst disable optional_qualifier @ +identifier noconst.A; +identifier noconst.func; +identifier b; +type T; +@@ + +func( ... ) { +<... +- T b = A; ++ const T b = A; +...> + } + +@ depends on noconst disable optional_qualifier @ +identifier noconst.A; +identifier noconst.func; +identifier b; +type T; +@@ + +func(...) + { +<... +- T b = (T) A; ++ const T b = A; +...> + } + +@ depends on noconst disable optional_qualifier @ +identifier noconst.A; +identifier noconst.func; +identifier b; +type T; +@@ + +func(...) + { +<... +- T b; ++ const T b; +... + b = A; +...> + } + +@ depends on noconst disable optional_qualifier @ +identifier noconst.A; +identifier noconst.func; +identifier b; +type T; +@@ + +func(...) + { +<... +- T b; ++ const T b; +... +- b = (T) A; ++ b = A; +...> + } diff --git a/zebra/main.c b/zebra/main.c index 184e798bd0..cff5e06933 100644 --- a/zebra/main.c +++ b/zebra/main.c @@ -119,8 +119,6 @@ struct zebra_privs_t zserv_privs = { .cap_num_p = array_size(_caps_p), .cap_num_i = 0}; -unsigned int multipath_num = MULTIPATH_NUM; - /* SIGHUP handler. */ static void sighup(void) { @@ -322,9 +320,9 @@ int main(int argc, char **argv) keep_kernel_mode = 1; break; case 'e': - multipath_num = atoi(optarg); - if (multipath_num > MULTIPATH_NUM - || multipath_num <= 0) { + zrouter.multipath_num = atoi(optarg); + if (zrouter.multipath_num > MULTIPATH_NUM + || zrouter.multipath_num <= 0) { flog_err( EC_ZEBRA_BAD_MULTIPATH_NUM, "Multipath Number specified must be less than %d and greater than 0", diff --git a/zebra/redistribute.c b/zebra/redistribute.c index fe064f847a..f3155deb14 100644 --- a/zebra/redistribute.c +++ b/zebra/redistribute.c @@ -653,7 +653,8 @@ int zebra_import_table(afi_t afi, uint32_t table_id, uint32_t distance, if (afi >= AFI_MAX) return (-1); - table = zebra_vrf_other_route_table(afi, table_id, VRF_DEFAULT); + table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, + table_id, VRF_DEFAULT); if (table == NULL) { return 0; } else if (IS_ZEBRA_DEBUG_RIB) { @@ -767,8 +768,8 @@ void zebra_import_table_rm_update(const char *rmap) rmap_name = zebra_get_import_table_route_map(afi, i); if ((!rmap_name) || (strcmp(rmap_name, rmap) != 0)) continue; - table = zebra_vrf_other_route_table(afi, i, - VRF_DEFAULT); + table = zebra_vrf_table_with_table_id(afi, SAFI_UNICAST, + i, VRF_DEFAULT); for (rn = route_top(table); rn; rn = route_next(rn)) { /* For each entry in the non-default * routing table, diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 817c65bf28..5088e2e8e1 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -42,6 +42,7 @@ #include "zebra/debug.h" #include "zebra/rib.h" #include "zebra/zapi_msg.h" +#include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" #include "zebra/zebra_errors.h" #include "zebra/zebra_router.h" @@ -80,25 +81,18 @@ enum rtadv_event { RTADV_READ }; -static void rtadv_event(struct zebra_vrf *, enum rtadv_event, int); +static void rtadv_event(struct zebra_ns *, enum rtadv_event, int); static int if_join_all_router(int, struct interface *); static int if_leave_all_router(int, struct interface *); -static int rtadv_get_socket(struct zebra_vrf *zvrf) -{ - if (zvrf->rtadv.sock >= 0) - return zvrf->rtadv.sock; - return zrouter.rtadv_sock; -} - -static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex) +static int rtadv_increment_received(struct zebra_ns *zns, ifindex_t *ifindex) { int ret = -1; struct interface *iface; struct zebra_if *zif; - iface = if_lookup_by_index(*ifindex, zvrf->vrf->vrf_id); + iface = if_lookup_by_index_per_ns(zns, *ifindex); if (iface && iface->info) { zif = iface->info; zif->ra_rcvd++; @@ -107,7 +101,7 @@ static int rtadv_increment_received(struct zebra_vrf *zvrf, ifindex_t *ifindex) return ret; } -static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf, +static int rtadv_recv_packet(struct zebra_ns *zns, int sock, uint8_t *buf, int buflen, struct sockaddr_in6 *from, ifindex_t *ifindex, int *hoplimit) { @@ -155,7 +149,7 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf, } } - rtadv_increment_received(zvrf, ifindex); + rtadv_increment_received(zns, ifindex); return ret; } @@ -467,19 +461,19 @@ no_more_opts: static int rtadv_timer(struct thread *thread) { - struct zebra_vrf *zvrf = THREAD_ARG(thread); + struct zebra_ns *zns = THREAD_ARG(thread); struct vrf *vrf; struct interface *ifp; struct zebra_if *zif; int period; - zvrf->rtadv.ra_timer = NULL; - if (zvrf->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(zvrf, RTADV_TIMER, 1 /* 1 s */); + rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */); } else { period = 10; /* 10 ms */ - rtadv_event(zvrf, RTADV_TIMER_MSEC, 10 /* 10 ms */); + rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */); } RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) @@ -506,7 +500,7 @@ static int rtadv_timer(struct thread *thread) "Fast RA Rexmit on interface %s", ifp->name); - rtadv_send_packet(rtadv_get_socket(zvrf), + rtadv_send_packet(zrouter.rtadv.sock, ifp); } else { zif->rtadv.AdvIntervalTimer -= period; @@ -520,8 +514,8 @@ static int rtadv_timer(struct thread *thread) zif->rtadv .MaxRtrAdvInterval; rtadv_send_packet( - rtadv_get_socket(zvrf), - ifp); + zrouter.rtadv.sock, + ifp); } } } @@ -533,9 +527,10 @@ static int rtadv_timer(struct thread *thread) static void rtadv_process_solicit(struct interface *ifp) { struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id); + struct zebra_ns *zns = zvrf->zns; - assert(zvrf); - rtadv_send_packet(rtadv_get_socket(zvrf), ifp); + assert(zns); + rtadv_send_packet(zrouter.rtadv.sock, ifp); } /* @@ -657,7 +652,7 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len, static void rtadv_process_packet(uint8_t *buf, unsigned int len, ifindex_t ifindex, int hoplimit, struct sockaddr_in6 *from, - struct zebra_vrf *zvrf) + struct zebra_ns *zns) { struct icmp6_hdr *icmph; struct interface *ifp; @@ -667,7 +662,7 @@ static void rtadv_process_packet(uint8_t *buf, unsigned int len, inet_ntop(AF_INET6, &from->sin6_addr, addr_str, INET6_ADDRSTRLEN); /* Interface search. */ - ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id); + ifp = if_lookup_by_index_per_ns(zns, ifindex); if (ifp == NULL) { flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE, "RA/RS received on unknown IF %u from %s", ifindex, @@ -729,15 +724,15 @@ static int rtadv_read(struct thread *thread) struct sockaddr_in6 from; ifindex_t ifindex = 0; int hoplimit = -1; - struct zebra_vrf *zvrf = THREAD_ARG(thread); + struct zebra_ns *zns = THREAD_ARG(thread); sock = THREAD_FD(thread); - zvrf->rtadv.ra_read = NULL; + zrouter.rtadv.ra_read = NULL; /* Register myself. */ - rtadv_event(zvrf, RTADV_READ, sock); + rtadv_event(zns, RTADV_READ, sock); - len = rtadv_recv_packet(zvrf, sock, buf, sizeof(buf), &from, &ifindex, + len = rtadv_recv_packet(zns, sock, buf, sizeof(buf), &from, &ifindex, &hoplimit); if (len < 0) { @@ -747,7 +742,7 @@ static int rtadv_read(struct thread *thread) return len; } - rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zvrf); + rtadv_process_packet(buf, (unsigned)len, ifindex, hoplimit, &from, zns); return 0; } @@ -880,27 +875,29 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, { struct zebra_if *zif; struct zebra_vrf *zvrf; + struct zebra_ns *zns; zif = ifp->info; zvrf = vrf_info_lookup(ifp->vrf_id); + zns = zvrf->zns; if (status == RA_SUPPRESS) { /* RA is currently enabled */ if (zif->rtadv.AdvSendAdvertisements) { zif->rtadv.AdvSendAdvertisements = 0; zif->rtadv.AdvIntervalTimer = 0; - zvrf->rtadv.adv_if_count--; + zrouter.rtadv.adv_if_count--; - if_leave_all_router(rtadv_get_socket(zvrf), ifp); + if_leave_all_router(zrouter.rtadv.sock, ifp); - if (zvrf->rtadv.adv_if_count == 0) - rtadv_event(zvrf, RTADV_STOP, 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; - zvrf->rtadv.adv_if_count++; + zrouter.rtadv.adv_if_count++; if (zif->rtadv.MaxRtrAdvInterval >= 1000) { /* Enable Fast RA only when RA interval is in @@ -910,11 +907,11 @@ static void ipv6_nd_suppress_ra_set(struct interface *ifp, RTADV_NUM_FAST_REXMITS; } - if_join_all_router(rtadv_get_socket(zvrf), ifp); + if_join_all_router(zrouter.rtadv.sock, ifp); - if (zvrf->rtadv.adv_if_count == 1) - rtadv_event(zvrf, RTADV_START, - rtadv_get_socket(zvrf)); + if (zrouter.rtadv.adv_if_count == 1) + rtadv_event(zns, RTADV_START, + zrouter.rtadv.sock); } } } @@ -947,7 +944,7 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable) zebra_route_string(client->proto), ra_interval); /* Locate interface and check VRF match. */ - ifp = if_lookup_by_index(ifindex, zvrf->vrf->vrf_id); + ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex); if (!ifp) { flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE, "%u: IF %u RA %s client %s - interface unknown", @@ -1054,9 +1051,6 @@ DEFUN (ipv6_nd_ra_interval_msec, VTY_DECLVAR_CONTEXT(interface, ifp); unsigned interval; struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf; - - zvrf = vrf_info_lookup(ifp->vrf_id); interval = strtoul(argv[idx_number]->arg, NULL, 10); if ((zif->rtadv.AdvDefaultLifetime != -1 @@ -1067,10 +1061,10 @@ DEFUN (ipv6_nd_ra_interval_msec, } if (zif->rtadv.MaxRtrAdvInterval % 1000) - zvrf->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; if (interval % 1000) - zvrf->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; @@ -1092,9 +1086,6 @@ DEFUN (ipv6_nd_ra_interval, VTY_DECLVAR_CONTEXT(interface, ifp); unsigned interval; struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf; - - zvrf = vrf_info_lookup(ifp->vrf_id); interval = strtoul(argv[idx_number]->arg, NULL, 10); if ((zif->rtadv.AdvDefaultLifetime != -1 @@ -1105,7 +1096,7 @@ DEFUN (ipv6_nd_ra_interval, } if (zif->rtadv.MaxRtrAdvInterval % 1000) - zvrf->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; /* convert to milliseconds */ interval = interval * 1000; @@ -1131,12 +1122,9 @@ DEFUN (no_ipv6_nd_ra_interval, { VTY_DECLVAR_CONTEXT(interface, ifp); struct zebra_if *zif = ifp->info; - struct zebra_vrf *zvrf = NULL; - - zvrf = vrf_info_lookup(ifp->vrf_id); if (zif->rtadv.MaxRtrAdvInterval % 1000) - zvrf->rtadv.adv_msec_if_count--; + zrouter.rtadv.adv_msec_if_count--; UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED); @@ -2106,15 +2094,15 @@ static int rtadv_config_write(struct vty *vty, struct interface *ifp) } -static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val) +static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val) { - struct rtadv *rtadv = &zvrf->rtadv; + struct rtadv *rtadv = &zrouter.rtadv; switch (event) { case RTADV_START: - thread_add_read(zrouter.master, rtadv_read, zvrf, val, + thread_add_read(zrouter.master, rtadv_read, zns, val, &rtadv->ra_read); - thread_add_event(zrouter.master, rtadv_timer, zvrf, 0, + thread_add_event(zrouter.master, rtadv_timer, zns, 0, &rtadv->ra_timer); break; case RTADV_STOP: @@ -2128,15 +2116,15 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val) } break; case RTADV_TIMER: - thread_add_timer(zrouter.master, rtadv_timer, zvrf, val, + thread_add_timer(zrouter.master, rtadv_timer, zns, val, &rtadv->ra_timer); break; case RTADV_TIMER_MSEC: - thread_add_timer_msec(zrouter.master, rtadv_timer, zvrf, val, + thread_add_timer_msec(zrouter.master, rtadv_timer, zns, val, &rtadv->ra_timer); break; case RTADV_READ: - thread_add_read(zrouter.master, rtadv_read, zvrf, val, + thread_add_read(zrouter.master, rtadv_read, zns, val, &rtadv->ra_read); break; default: @@ -2145,29 +2133,21 @@ static void rtadv_event(struct zebra_vrf *zvrf, enum rtadv_event event, int val) return; } -void rtadv_init(struct zebra_vrf *zvrf) +void rtadv_init(struct zebra_ns *zns) { - if (vrf_is_backend_netns()) { - zvrf->rtadv.sock = rtadv_make_socket(zvrf->zns->ns_id); - zrouter.rtadv_sock = -1; - } else if (!zrouter.rtadv_sock) { - zvrf->rtadv.sock = -1; - zrouter.rtadv_sock = rtadv_make_socket(zvrf->zns->ns_id); - } + zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id); } -void rtadv_terminate(struct zebra_vrf *zvrf) +void rtadv_terminate(struct zebra_ns *zns) { - rtadv_event(zvrf, RTADV_STOP, 0); - if (zvrf->rtadv.sock >= 0) { - close(zvrf->rtadv.sock); - zvrf->rtadv.sock = -1; - } else if (zrouter.rtadv_sock >= 0) { - close(zrouter.rtadv_sock); - zrouter.rtadv_sock = -1; + rtadv_event(zns, RTADV_STOP, 0); + if (zrouter.rtadv.sock >= 0) { + close(zrouter.rtadv.sock); + zrouter.rtadv.sock = -1; } - zvrf->rtadv.adv_if_count = 0; - zvrf->rtadv.adv_msec_if_count = 0; + + zrouter.rtadv.adv_if_count = 0; + zrouter.rtadv.adv_msec_if_count = 0; } void rtadv_cmd_init(void) @@ -2263,11 +2243,11 @@ static int if_leave_all_router(int sock, struct interface *ifp) } #else -void rtadv_init(struct zebra_vrf *zvrf) +void rtadv_init(struct zebra_ns *zns) { /* Empty.*/; } -void rtadv_terminate(struct zebra_vrf *zvrf) +void rtadv_terminate(struct zebra_ns *zns) { /* Empty.*/; } diff --git a/zebra/rtadv.h b/zebra/rtadv.h index 8ad3de7f17..53c497fc09 100644 --- a/zebra/rtadv.h +++ b/zebra/rtadv.h @@ -135,8 +135,8 @@ typedef enum { RA_SUPPRESS, } ipv6_nd_suppress_ra_status; -extern void rtadv_init(struct zebra_vrf *); -extern void rtadv_terminate(struct zebra_vrf *); +extern void rtadv_init(struct zebra_ns *); +extern void rtadv_terminate(struct zebra_ns *); extern void rtadv_cmd_init(void); extern void zebra_interface_radv_disable(ZAPI_HANDLER_ARGS); extern void zebra_interface_radv_enable(ZAPI_HANDLER_ARGS); diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 974cc9de30..03b9653ce6 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1339,14 +1339,14 @@ static void zread_interface_delete(ZAPI_HANDLER_ARGS) void zserv_nexthop_num_warn(const char *caller, const struct prefix *p, const unsigned int nexthop_num) { - if (nexthop_num > multipath_num) { + if (nexthop_num > zrouter.multipath_num) { char buff[PREFIX2STR_BUFFER]; prefix2str(p, buff, sizeof(buff)); flog_warn( EC_ZEBRA_MORE_NH_THAN_MULTIPATH, "%s: Prefix %s has %d nexthops, but we can only use the first %d", - caller, buff, nexthop_num, multipath_num); + caller, buff, nexthop_num, zrouter.multipath_num); } } @@ -1651,7 +1651,7 @@ static void zsend_capabilities(struct zserv *client, struct zebra_vrf *zvrf) zclient_create_header(s, ZEBRA_CAPABILITIES, zvrf->vrf->vrf_id); stream_putl(s, vrf_get_backend()); stream_putc(s, mpls_enabled); - stream_putl(s, multipath_num); + stream_putl(s, zrouter.multipath_num); stream_putc(s, zebra_mlag_get_role()); stream_putw_at(s, 0, stream_get_endp(s)); diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c index 16459b606a..065bdee208 100644 --- a/zebra/zebra_fpm_netlink.c +++ b/zebra/zebra_fpm_netlink.c @@ -32,6 +32,7 @@ #include "prefix.h" #include "zebra/zserv.h" +#include "zebra/zebra_router.h" #include "zebra/zebra_dplane.h" #include "zebra/zebra_ns.h" #include "zebra/zebra_vrf.h" @@ -251,7 +252,7 @@ static int netlink_route_info_fill(netlink_route_info_t *ri, int cmd, ri->metric = &re->metric; for (ALL_NEXTHOPS(re->ng, nexthop)) { - if (ri->num_nhs >= multipath_num) + if (ri->num_nhs >= zrouter.multipath_num) break; if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) diff --git a/zebra/zebra_fpm_protobuf.c b/zebra/zebra_fpm_protobuf.c index 0f95c9ba8b..3054b8a34d 100644 --- a/zebra/zebra_fpm_protobuf.c +++ b/zebra/zebra_fpm_protobuf.c @@ -34,6 +34,7 @@ #include "qpb/linear_allocator.h" #include "fpm/fpm_pb.h" +#include "zebra_router.h" #include "zebra_fpm_private.h" /* @@ -173,7 +174,7 @@ static Fpm__AddRoute *create_add_route_message(qpb_allocator_t *allocator, */ num_nhs = 0; for (ALL_NEXTHOPS(re->ng, nexthop)) { - if (num_nhs >= multipath_num) + if (num_nhs >= zrouter.multipath_num) break; if (num_nhs >= array_size(nexthops)) diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c index f1082a5996..5356a7f498 100644 --- a/zebra/zebra_mpls.c +++ b/zebra/zebra_mpls.c @@ -76,7 +76,7 @@ static zebra_fec_t *fec_add(struct route_table *table, struct prefix *p, uint32_t label_index); static int fec_del(zebra_fec_t *fec); -static unsigned int label_hash(void *p); +static unsigned int label_hash(const void *p); static bool label_cmp(const void *p1, const void *p2); static int nhlfe_nexthop_active_ipv4(zebra_nhlfe_t *nhlfe, struct nexthop *nexthop); @@ -577,7 +577,7 @@ static int fec_del(zebra_fec_t *fec) /* * Hash function for label. */ -static unsigned int label_hash(void *p) +static unsigned int label_hash(const void *p) { const zebra_ile_t *ile = p; diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c index 977a8eaf3c..e7fdaf127d 100644 --- a/zebra/zebra_mpls_openbsd.c +++ b/zebra/zebra_mpls_openbsd.c @@ -27,6 +27,7 @@ #include "zebra/zebra_mpls.h" #include "zebra/debug.h" #include "zebra/zebra_errors.h" +#include "zebra/zebra_router.h" #include "privs.h" #include "prefix.h" @@ -262,7 +263,7 @@ static int kernel_lsp_cmd(struct zebra_dplane_ctx *ctx) if (!nexthop) continue; - if (nexthop_num >= multipath_num) + if (nexthop_num >= zrouter.multipath_num) break; if (((action == RTM_ADD || action == RTM_CHANGE) diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index db4f9d0015..0c743d8678 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -27,6 +27,7 @@ #include "lib/prefix.h" #include "lib/memory.h" +#include "rtadv.h" #include "zebra_ns.h" #include "zebra_vrf.h" #include "zebra_memory.h" @@ -121,6 +122,10 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) zns->ns_id = ns_id; +#if defined(HAVE_RTADV) + rtadv_init(zns); +#endif + kernel_init(zns); interface_list(zns); route_read(zns); @@ -137,6 +142,9 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) static int zebra_ns_disable_internal(struct zebra_ns *zns, bool complete) { route_table_finish(zns->if_table); +#if defined(HAVE_RTADV) + rtadv_terminate(zns); +#endif kernel_terminate(zns, complete); diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 73db567eac..a82dd4c24a 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -135,12 +135,12 @@ void zebra_pbr_rules_free(void *arg) XFREE(MTYPE_TMP, rule); } -uint32_t zebra_pbr_rules_hash_key(void *arg) +uint32_t zebra_pbr_rules_hash_key(const void *arg) { - struct zebra_pbr_rule *rule; + const struct zebra_pbr_rule *rule; uint32_t key; - rule = (struct zebra_pbr_rule *)arg; + rule = arg; key = jhash_3words(rule->rule.seq, rule->rule.priority, rule->rule.action.table, prefix_hash_key(&rule->rule.filter.src_ip)); @@ -250,9 +250,9 @@ void zebra_pbr_ipset_free(void *arg) XFREE(MTYPE_TMP, ipset); } -uint32_t zebra_pbr_ipset_hash_key(void *arg) +uint32_t zebra_pbr_ipset_hash_key(const void *arg) { - struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg; + const struct zebra_pbr_ipset *ipset = arg; uint32_t *pnt = (uint32_t *)&ipset->ipset_name; uint32_t key = jhash_1word(ipset->vrf_id, 0x63ab42de); @@ -290,12 +290,12 @@ void zebra_pbr_ipset_entry_free(void *arg) XFREE(MTYPE_TMP, ipset); } -uint32_t zebra_pbr_ipset_entry_hash_key(void *arg) +uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg) { - struct zebra_pbr_ipset_entry *ipset; + const struct zebra_pbr_ipset_entry *ipset; uint32_t key; - ipset = (struct zebra_pbr_ipset_entry *)arg; + ipset = arg; key = prefix_hash_key(&ipset->src); key = jhash_1word(ipset->unique, key); key = jhash_1word(prefix_hash_key(&ipset->dst), key); @@ -359,9 +359,9 @@ void zebra_pbr_iptable_free(void *arg) XFREE(MTYPE_TMP, iptable); } -uint32_t zebra_pbr_iptable_hash_key(void *arg) +uint32_t zebra_pbr_iptable_hash_key(const void *arg) { - struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg; + const struct zebra_pbr_iptable *iptable = arg; uint32_t *pnt = (uint32_t *)&(iptable->ipset_name); uint32_t key; diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index 0d55491107..cc1cc5acd5 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -211,7 +211,7 @@ extern void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable, 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 uint32_t zebra_pbr_rules_hash_key(const void *arg); extern bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); /* has operates on 32bit pointer @@ -220,16 +220,16 @@ extern bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); #define ZEBRA_IPSET_NAME_HASH_SIZE (ZEBRA_IPSET_NAME_SIZE / 4) extern void zebra_pbr_ipset_free(void *arg); -extern uint32_t zebra_pbr_ipset_hash_key(void *arg); +extern uint32_t zebra_pbr_ipset_hash_key(const void *arg); 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 uint32_t zebra_pbr_ipset_entry_hash_key(const void *arg); 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 uint32_t zebra_pbr_iptable_hash_key(const void *arg); extern bool zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2); extern void zebra_pbr_init(void); diff --git a/zebra/zebra_ptm.c b/zebra/zebra_ptm.c index d3ecd3695a..46f1385520 100644 --- a/zebra/zebra_ptm.c +++ b/zebra/zebra_ptm.c @@ -93,6 +93,7 @@ const char ZEBRA_PTM_BFD_IFNAME_FIELD[] = "ifName"; const char ZEBRA_PTM_BFD_MAX_HOP_CNT_FIELD[] = "maxHopCnt"; const char ZEBRA_PTM_BFD_SEND_EVENT[] = "sendEvent"; const char ZEBRA_PTM_BFD_VRF_NAME_FIELD[] = "vrfName"; +const char ZEBRA_PTM_BFD_CBIT_FIELD[] = "bfdcbit"; static ptm_lib_handle_t *ptm_hdl; @@ -688,6 +689,7 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS) char tmp_buf[64]; int data_len = ZEBRA_PTM_SEND_MAX_SOCKBUF; unsigned int pid; + uint8_t cbit_set; if (hdr->command == ZEBRA_BFD_DEST_UPDATE) client->bfd_peer_upd8_cnt++; @@ -813,6 +815,10 @@ void zebra_ptm_bfd_dst_register(ZAPI_HANDLER_ARGS) ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_IFNAME_FIELD, if_name); } + STREAM_GETC(s, cbit_set); + sprintf(tmp_buf, "%d", cbit_set); + ptm_lib_append_msg(ptm_hdl, out_ctxt, + ZEBRA_PTM_BFD_CBIT_FIELD, tmp_buf); sprintf(tmp_buf, "%d", 1); ptm_lib_append_msg(ptm_hdl, out_ctxt, ZEBRA_PTM_BFD_SEND_EVENT, diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index eddf6c8158..8d4f49e3ee 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -955,7 +955,8 @@ static int nexthop_active_update(struct route_node *rn, struct route_entry *re) * decision point. */ new_active = nexthop_active_check(rn, re, nexthop); - if (new_active && re->nexthop_active_num >= multipath_num) { + if (new_active + && re->nexthop_active_num >= zrouter.multipath_num) { UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE); new_active = 0; } @@ -3207,18 +3208,23 @@ unsigned long rib_score_proto(uint8_t proto, unsigned short instance) { struct vrf *vrf; struct zebra_vrf *zvrf; + struct other_route_table *ort; unsigned long cnt = 0; - RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) - if ((zvrf = vrf->info) != NULL) - cnt += rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP][SAFI_UNICAST]) - + rib_score_proto_table( - proto, instance, - zvrf->table[AFI_IP6][SAFI_UNICAST]); + RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id) { + zvrf = vrf->info; + if (!zvrf) + continue; - cnt += zebra_router_score_proto(proto, instance); + cnt += rib_score_proto_table(proto, instance, + zvrf->table[AFI_IP][SAFI_UNICAST]) + + rib_score_proto_table( + proto, instance, + zvrf->table[AFI_IP6][SAFI_UNICAST]); + + for_each(otable, &zvrf->other_tables, ort) cnt += + rib_score_proto_table(proto, instance, ort->table); + } return cnt; } diff --git a/zebra/zebra_routemap.c b/zebra/zebra_routemap.c index 5355fa062e..f48bf3b033 100644 --- a/zebra/zebra_routemap.c +++ b/zebra/zebra_routemap.c @@ -705,6 +705,9 @@ DEFPY (ip_protocol, { int ret, rtype; + assert(proto); + assert(rmap); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -737,6 +740,8 @@ DEFPY (no_ip_protocol, { int ret, rtype; + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -781,6 +786,9 @@ DEFPY (ipv6_protocol, { int ret, rtype; + assert(rmap); + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -813,6 +821,8 @@ DEFPY (no_ipv6_protocol, { int ret, rtype; + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -858,6 +868,9 @@ DEFPY (ip_protocol_nht_rmap, int ret, rtype; + assert(proto); + assert(rmap); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -890,6 +903,8 @@ DEFPY (no_ip_protocol_nht_rmap, { int ret, rtype; + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -935,6 +950,9 @@ DEFPY (ipv6_protocol_nht_rmap, { int ret, rtype; + assert(rmap); + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) @@ -967,6 +985,8 @@ DEFPY (no_ipv6_protocol_nht_rmap, { int ret, rtype; + assert(proto); + ZEBRA_DECLVAR_CONTEXT(vrf, zvrf); if (!zvrf) diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c index 63724fc350..610d51d3ea 100644 --- a/zebra/zebra_router.c +++ b/zebra/zebra_router.c @@ -30,7 +30,9 @@ #include "zebra_vxlan.h" #include "zebra_mlag.h" -struct zebra_router zrouter; +struct zebra_router zrouter = { + .multipath_num = MULTIPATH_NUM, +}; static inline int zebra_router_table_entry_compare(const struct zebra_router_table *e1, @@ -117,19 +119,6 @@ struct route_table *zebra_router_get_table(struct zebra_vrf *zvrf, 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_show_table_summary(struct vty *vty) { struct zebra_router_table *zrt; diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h index c1f07397d0..b3def297ac 100644 --- a/zebra/zebra_router.h +++ b/zebra/zebra_router.h @@ -82,8 +82,9 @@ struct zebra_router { struct hash *iptable_hash; - /* used if vrf backend is not network namespace */ - int rtadv_sock; +#if defined(HAVE_RTADV) + struct rtadv rtadv; +#endif /* HAVE_RTADV */ /* A sequence number used for tracking routes */ _Atomic uint32_t sequence_num; @@ -109,6 +110,8 @@ struct zebra_router { * The EVPN instance, if any */ struct zebra_vrf *evpn_vrf; + + uint32_t multipath_num; }; extern struct zebra_router zrouter; @@ -127,8 +130,6 @@ extern void zebra_router_release_table(struct zebra_vrf *zvrf, uint32_t tableid, 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); extern void zebra_router_show_table_summary(struct vty *vty); diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c index 1f2ff63286..6343054943 100644 --- a/zebra/zebra_vrf.c +++ b/zebra/zebra_vrf.c @@ -29,7 +29,6 @@ #include "vty.h" #include "zebra/zebra_router.h" -#include "zebra/rtadv.h" #include "zebra/debug.h" #include "zebra/zapi_msg.h" #include "zebra/rib.h" @@ -48,6 +47,8 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi, static void zebra_rnhtable_node_cleanup(struct route_table *table, struct route_node *node); +DEFINE_MTYPE_STATIC(ZEBRA, OTHER_TABLE, "Other Table"); + /* VRF information update. */ static void zebra_vrf_add_update(struct zebra_vrf *zvrf) { @@ -94,6 +95,9 @@ static int zebra_vrf_new(struct vrf *vrf) zvrf = zebra_vrf_alloc(); vrf->info = zvrf; zvrf->vrf = vrf; + + otable_init(&zvrf->other_tables); + router_id_init(zvrf); return 0; } @@ -115,10 +119,6 @@ static int zebra_vrf_enable(struct vrf *vrf) zvrf->zns = zebra_ns_lookup((ns_id_t)vrf->vrf_id); else zvrf->zns = zebra_ns_lookup(NS_DEFAULT); -#if defined(HAVE_RTADV) - rtadv_init(zvrf); -#endif - /* Inform clients that the VRF is now active. This is an * add for the clients. */ @@ -161,10 +161,6 @@ static int zebra_vrf_disable(struct vrf *vrf) /* Stop any VxLAN-EVPN processing. */ zebra_vxlan_vrf_disable(zvrf); -#if defined(HAVE_RTADV) - rtadv_terminate(zvrf); -#endif - /* Inform clients that the VRF is now inactive. This is a * delete for the clients. */ @@ -235,6 +231,7 @@ static int zebra_vrf_disable(struct vrf *vrf) static int zebra_vrf_delete(struct vrf *vrf) { struct zebra_vrf *zvrf = vrf->info; + struct other_route_table *otable; struct route_table *table; afi_t afi; safi_t safi; @@ -283,11 +280,22 @@ static int zebra_vrf_delete(struct vrf *vrf) route_table_finish(zvrf->import_check_table[afi]); } + otable = otable_pop(&zvrf->other_tables); + while (otable) { + zebra_router_release_table(zvrf, otable->table_id, + otable->afi, otable->safi); + XFREE(MTYPE_OTHER_TABLE, otable); + + otable = otable_pop(&zvrf->other_tables); + } + /* Cleanup EVPN states for vrf */ zebra_vxlan_vrf_delete(zvrf); list_delete_all_node(zvrf->rid_all_sorted_list); list_delete_all_node(zvrf->rid_lo_sorted_list); + + otable_fini(&zvrf->other_tables); XFREE(MTYPE_ZEBRA_VRF, zvrf); vrf->info = NULL; @@ -329,25 +337,34 @@ struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, uint32_t table_id) { - struct route_table *table = NULL; + struct zebra_vrf *zvrf = vrf_info_lookup(vrf_id); + struct other_route_table ort, *otable; + struct route_table *table; + + if (!zvrf) + return NULL; if (afi >= AFI_MAX || safi >= SAFI_MAX) return NULL; - if (vrf_id == VRF_DEFAULT) { - if (table_id == RT_TABLE_MAIN) - table = zebra_vrf_table(afi, safi, vrf_id); - else - table = zebra_vrf_other_route_table(afi, table_id, - vrf_id); - } else if (vrf_is_backend_netns()) { - if (table_id == RT_TABLE_MAIN) - table = zebra_vrf_table(afi, safi, vrf_id); - else - table = zebra_vrf_other_route_table(afi, table_id, - vrf_id); - } else - table = zebra_vrf_table(afi, safi, vrf_id); + if (table_id == zvrf->table_id) + return zebra_vrf_table(afi, safi, vrf_id); + + ort.afi = afi; + ort.safi = safi; + ort.table_id = table_id; + otable = otable_find(&zvrf->other_tables, &ort); + if (otable) + return otable->table; + + table = zebra_router_get_table(zvrf, table_id, afi, safi); + + otable = XCALLOC(MTYPE_OTHER_TABLE, sizeof(*otable)); + otable->afi = afi; + otable->safi = safi; + otable->table_id = table_id; + otable->table = table; + otable_add(&zvrf->other_tables, otable); return table; } @@ -447,32 +464,6 @@ struct route_table *zebra_vrf_table(afi_t afi, safi_t safi, vrf_id_t vrf_id) return zvrf->table[afi][safi]; } -struct route_table *zebra_vrf_other_route_table(afi_t afi, uint32_t table_id, - vrf_id_t vrf_id) -{ - struct zebra_vrf *zvrf; - - zvrf = vrf_info_lookup(vrf_id); - if (!zvrf) - return NULL; - - if (afi >= AFI_MAX) - return NULL; - - if (table_id != RT_TABLE_MAIN) { - if (zvrf->table_id == RT_TABLE_MAIN) { - /* this VRF use default table - * so in all cases, it does not use specific table - * so it is possible to configure tables in this VRF - */ - return zebra_router_get_table(zvrf, table_id, afi, - SAFI_UNICAST); - } - } - - return zvrf->table[afi][SAFI_UNICAST]; -} - static int vrf_config_write(struct vty *vty) { struct vrf *vrf; diff --git a/zebra/zebra_vrf.h b/zebra/zebra_vrf.h index 2dd47b5561..febaf3c844 100644 --- a/zebra/zebra_vrf.h +++ b/zebra/zebra_vrf.h @@ -43,6 +43,18 @@ struct zebra_rmap { struct route_map *map; }; +PREDECL_RBTREE_UNIQ(otable); + +struct other_route_table { + struct otable_item next; + + afi_t afi; + safi_t safi; + uint32_t table_id; + + struct route_table *table; +}; + /* Routing table instance. */ struct zebra_vrf { /* Back pointer */ @@ -69,6 +81,8 @@ struct zebra_vrf { /* Import check table (used mostly by BGP */ struct route_table *import_check_table[AFI_MAX]; + struct otable_head other_tables; + /* 2nd pointer type used primarily to quell a warning on * ALL_LIST_ELEMENTS_RO */ @@ -155,10 +169,6 @@ struct zebra_vrf { uint64_t lsp_removals_queued; uint64_t lsp_installs; uint64_t lsp_removals; - -#if defined(HAVE_RTADV) - struct rtadv rtadv; -#endif /* HAVE_RTADV */ }; #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 @@ -196,6 +206,25 @@ static inline bool zvrf_is_active(struct zebra_vrf *zvrf) return zvrf->vrf->status & VRF_ACTIVE; } +static inline int +zvrf_other_table_compare_func(const struct other_route_table *a, + const struct other_route_table *b) +{ + if (a->afi != b->afi) + return a->afi - b->afi; + + if (a->safi != b->safi) + return a->safi - b->safi; + + if (a->table_id != b->table_id) + return a->table_id - b->table_id; + + return 0; +} + +DECLARE_RBTREE_UNIQ(otable, struct other_route_table, next, + zvrf_other_table_compare_func) + struct route_table *zebra_vrf_table_with_table_id(afi_t afi, safi_t safi, vrf_id_t vrf_id, uint32_t table_id); @@ -206,8 +235,6 @@ extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *); extern struct zebra_vrf *zebra_vrf_alloc(void); extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t); -extern struct route_table * -zebra_vrf_other_route_table(afi_t afi, uint32_t table_id, vrf_id_t vrf_id); extern int zebra_vrf_has_config(struct zebra_vrf *zvrf); extern void zebra_vrf_init(void); diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c index 605e9eae66..feb0aadfa8 100644 --- a/zebra/zebra_vxlan.c +++ b/zebra/zebra_vxlan.c @@ -93,7 +93,7 @@ static void zvni_print_hash(struct hash_bucket *bucket, void *ctxt[]); static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, struct ipaddr *ip, uint8_t flags, uint32_t seq, int state, uint16_t cmd); -static unsigned int neigh_hash_keymake(void *p); +static unsigned int neigh_hash_keymake(const void *p); static void *zvni_neigh_alloc(void *p); static zebra_neigh_t *zvni_neigh_add(zebra_vni_t *zvni, struct ipaddr *ip, struct ethaddr *mac); @@ -149,7 +149,7 @@ static struct interface *zl3vni_map_to_vxlan_if(zebra_l3vni_t *zl3vni); 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 unsigned int mac_hash_keymake(const void *p); 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); @@ -168,7 +168,7 @@ static int zvni_mac_install(zebra_vni_t *zvni, zebra_mac_t *mac); static int zvni_mac_uninstall(zebra_vni_t *zvni, zebra_mac_t *mac); static void zvni_install_mac_hash(struct hash_bucket *bucket, void *ctxt); -static unsigned int vni_hash_keymake(void *p); +static unsigned int vni_hash_keymake(const void *p); static void *zvni_alloc(void *p); static zebra_vni_t *zvni_lookup(vni_t vni); static zebra_vni_t *zvni_add(vni_t vni); @@ -213,7 +213,7 @@ static void zebra_vxlan_dup_addr_detect_for_mac(struct zebra_vrf *zvrf, bool do_dad, bool *is_dup_detect, bool is_local); -static unsigned int zebra_vxlan_sg_hash_key_make(void *p); +static unsigned int zebra_vxlan_sg_hash_key_make(const void *p); static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2); static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf, struct in_addr sip, struct in_addr mcast_grp); @@ -2158,10 +2158,10 @@ static int zvni_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr, /* * Make hash key for neighbors. */ -static unsigned int neigh_hash_keymake(void *p) +static unsigned int neigh_hash_keymake(const void *p) { - zebra_neigh_t *n = p; - struct ipaddr *ip = &n->ip; + const zebra_neigh_t *n = p; + const struct ipaddr *ip = &n->ip; if (IS_IPADDR_V4(ip)) return jhash_1word(ip->ipaddr_v4.s_addr, 0); @@ -3296,9 +3296,9 @@ static int zvni_remote_neigh_update(zebra_vni_t *zvni, /* * Make hash key for MAC. */ -static unsigned int mac_hash_keymake(void *p) +static unsigned int mac_hash_keymake(const void *p) { - zebra_mac_t *pmac = p; + const zebra_mac_t *pmac = p; const void *pnt = (void *)pmac->macaddr.octet; return jhash(pnt, ETH_ALEN, 0xa5a5a55a); @@ -3815,7 +3815,7 @@ static void zvni_read_mac_neigh(zebra_vni_t *zvni, struct interface *ifp) /* * Hash function for VNI. */ -static unsigned int vni_hash_keymake(void *p) +static unsigned int vni_hash_keymake(const void *p) { const zebra_vni_t *zvni = p; @@ -4688,7 +4688,7 @@ static int zl3vni_local_nh_del(zebra_l3vni_t *zl3vni, struct ipaddr *ip) /* * Hash function for L3 VNI. */ -static unsigned int l3vni_hash_keymake(void *p) +static unsigned int l3vni_hash_keymake(const void *p) { const zebra_l3vni_t *zl3vni = p; @@ -9457,9 +9457,9 @@ static int zebra_vxlan_sg_send(struct prefix_sg *sg, return zserv_send_message(client, s); } -static unsigned int zebra_vxlan_sg_hash_key_make(void *p) +static unsigned int zebra_vxlan_sg_hash_key_make(const void *p) { - zebra_vxlan_sg_t *vxlan_sg = p; + const zebra_vxlan_sg_t *vxlan_sg = p; return (jhash_2words(vxlan_sg->sg.src.s_addr, vxlan_sg->sg.grp.s_addr, 0)); diff --git a/zebra/zserv.h b/zebra/zserv.h index d6fdc05374..34965618f2 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -173,8 +173,6 @@ struct zserv { DECLARE_HOOK(zserv_client_connect, (struct zserv *client), (client)); DECLARE_KOOH(zserv_client_close, (struct zserv *client), (client)); -extern unsigned int multipath_num; - /* * Initialize Zebra API server. * |
