diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 574ece8cc5..c91a2ab6bd 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -558,9 +558,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, return 0; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, not installing remote macip", + __PRETTY_FUNCTION__); return 0; - + } s = zclient->obuf; stream_reset(s); @@ -616,8 +619,12 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, return 0; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, not installing remote vtep", + __PRETTY_FUNCTION__); return 0; + } s = zclient->obuf; stream_reset(s); diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 5ed6fd6ebe..2ef792e129 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -628,7 +628,10 @@ static void bgp_show_nexthops(struct vty *vty, struct bgp *bgp, int detail) if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_CONNECTED)) vty_out(vty, " Must be Connected\n"); - } + if (!CHECK_FLAG(bnc->flags, + BGP_NEXTHOP_REGISTERED)) + vty_out(vty, " Is not Registered\n"); + } tbuf = time(NULL) - (bgp_clock() - bnc->last_update); vty_out(vty, " Last update: %s", ctime(&tbuf)); vty_out(vty, "\n"); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index e764860bcc..8aa7798af4 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -240,8 +240,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, UNSET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); } if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW) { - bnc->flags |= BGP_NEXTHOP_REGISTERED; - bnc->flags |= BGP_NEXTHOP_VALID; + SET_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED); + SET_FLAG(bnc->flags, BGP_NEXTHOP_VALID); } else if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED)) register_zebra_rnh(bnc, is_bgp_static_route); if (pi && pi->nexthop != bnc) { @@ -587,9 +587,18 @@ static void sendmsg_zebra_rnh(struct bgp_nexthop_cache *bnc, int command) return; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bnc->bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, not installing NHT entry", + __PRETTY_FUNCTION__); return; + } + if (!bgp_zebra_num_connects()) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: We have not connected yet, cannot send nexthops", + __PRETTY_FUNCTION__); + } p = &(bnc->node->p); if ((command == ZEBRA_NEXTHOP_REGISTER || command == ZEBRA_IMPORT_ROUTE_REGISTER) @@ -802,3 +811,30 @@ void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc, path->nexthop->path_count++; } } + +/* + * This function is called to register nexthops to zebra + * as that we may have tried to install the nexthops + * before we actually have a zebra connection + */ +void bgp_nht_register_nexthops(struct bgp *bgp) +{ + struct bgp_node *rn; + struct bgp_nexthop_cache *bnc; + afi_t afi; + + for (afi = AFI_IP; afi < AFI_MAX; afi++) { + if (!bgp->nexthop_cache_table[afi]) + continue; + + for (rn = bgp_table_top(bgp->nexthop_cache_table[afi]); rn; + rn = bgp_route_next(rn)) { + bnc = bgp_nexthop_get_node_info(rn); + + if (!bnc) + continue; + + register_zebra_rnh(bnc, 0); + } + } +} diff --git a/bgpd/bgp_nht.h b/bgpd/bgp_nht.h index 0cc045a065..96dd915596 100644 --- a/bgpd/bgp_nht.h +++ b/bgpd/bgp_nht.h @@ -81,5 +81,11 @@ extern void bgp_cleanup_nexthops(struct bgp *bgp); */ extern void path_nh_map(struct bgp_path_info *path, struct bgp_nexthop_cache *bnc, bool make); +/* + * When we actually have the connection to + * the zebra daemon, we need to reregister + * any nexthops we may have sitting around + */ +extern void bgp_nht_register_nexthops(struct bgp *bgp); #endif /* _BGP_NHT_H */ diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 81a5be9d0c..50b790eb11 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -68,8 +68,11 @@ static inline int bgp_install_info_to_zebra(struct bgp *bgp) if (zclient->sock <= 0) return 0; - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + zlog_debug("%s: No zebra instance to talk to, not installing information", + __PRETTY_FUNCTION__); return 0; + } return 1; } @@ -1834,6 +1837,8 @@ void bgp_zebra_instance_register(struct bgp *bgp) */ if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT && is_evpn_enabled()) bgp_zebra_advertise_all_vni(bgp, 1); + + bgp_nht_register_nexthops(bgp); } /* Deregister this instance with Zebra. Invoked upon the instance @@ -1895,8 +1900,12 @@ int bgp_zebra_advertise_subnet(struct bgp *bgp, int advertise, vni_t vni) return 0; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, cannot advertise subnet", + __PRETTY_FUNCTION__); return 0; + } s = zclient->obuf; stream_reset(s); @@ -1918,8 +1927,12 @@ int bgp_zebra_advertise_gw_macip(struct bgp *bgp, int advertise, vni_t vni) return 0; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, not installing gw_macip", + __PRETTY_FUNCTION__); return 0; + } s = zclient->obuf; stream_reset(s); @@ -1942,8 +1955,12 @@ int bgp_zebra_vxlan_flood_control(struct bgp *bgp, return 0; /* Don't try to register if Zebra doesn't know of this instance. */ - if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zebra instance to talk to, not installing all vni", + __PRETTY_FUNCTION__); return 0; + } s = zclient->obuf; stream_reset(s); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index be092e9501..19384eec2f 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3072,9 +3072,12 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name, bgp_handle_socket(bgp, vrf, VRF_UNKNOWN, true); listnode_add(bm->bgp, bgp); - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: Registering BGP instance %s to zebra", + __PRETTY_FUNCTION__, name); bgp_zebra_instance_register(bgp); - + } return 0; } @@ -3218,8 +3221,12 @@ int bgp_delete(struct bgp *bgp) } /* Deregister from Zebra, if needed */ - if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) + if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: deregistering this bgp %s instance from zebra", + __PRETTY_FUNCTION__, bgp->name); bgp_zebra_instance_deregister(bgp); + } /* Remove visibility via the master list - there may however still be * routes to be processed still referencing the struct bgp. diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 7ea0a4d47d..42b0a81510 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1056,6 +1056,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) STREAM_GETC(s, p.prefixlen); l += 4; if (p.family == AF_INET) { + client->v4_nh_watch_add_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { zlog_debug( "%s: Specified prefix hdr->length %d is too large for a v4 address", @@ -1065,6 +1066,7 @@ static void zread_rnh_register(ZAPI_HANDLER_ARGS) STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; } else if (p.family == AF_INET6) { + client->v6_nh_watch_add_cnt++; if (p.prefixlen > IPV6_MAX_BITLEN) { zlog_debug( "%s: Specified prefix hdr->length %d is to large for a v6 address", @@ -1139,6 +1141,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) STREAM_GETC(s, p.prefixlen); l += 4; if (p.family == AF_INET) { + client->v4_nh_watch_rem_cnt++; if (p.prefixlen > IPV4_MAX_BITLEN) { zlog_debug( "%s: Specified prefix hdr->length %d is to large for a v4 address", @@ -1148,6 +1151,7 @@ static void zread_rnh_unregister(ZAPI_HANDLER_ARGS) STREAM_GET(&p.u.prefix4.s_addr, s, IPV4_MAX_BYTELEN); l += IPV4_MAX_BYTELEN; } else if (p.family == AF_INET6) { + client->v6_nh_watch_rem_cnt++; if (p.prefixlen > IPV6_MAX_BITLEN) { zlog_debug( "%s: Specified prefix hdr->length %d is to large for a v6 address", diff --git a/zebra/zserv.c b/zebra/zserv.c index 8cc462577a..3c3bf4077b 100644 --- a/zebra/zserv.c +++ b/zebra/zserv.c @@ -940,6 +940,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client) client->ifdel_cnt); vty_out(vty, "BFD peer %-12d%-12d%-12d\n", client->bfd_peer_add_cnt, client->bfd_peer_upd8_cnt, client->bfd_peer_del_cnt); + vty_out(vty, "NHT v4 %-12d%-12d%-12d\n", + client->v4_nh_watch_add_cnt, 0, client->v4_nh_watch_rem_cnt); + vty_out(vty, "NHT v6 %-12d%-12d%-12d\n", + client->v6_nh_watch_add_cnt, 0, client->v6_nh_watch_rem_cnt); vty_out(vty, "Interface Up Notifications: %d\n", client->ifup_cnt); vty_out(vty, "Interface Down Notifications: %d\n", client->ifdown_cnt); vty_out(vty, "VNI add notifications: %d\n", client->vniadd_cnt); diff --git a/zebra/zserv.h b/zebra/zserv.h index 987c67635d..f21ea17fe8 100644 --- a/zebra/zserv.h +++ b/zebra/zserv.h @@ -133,6 +133,10 @@ struct zserv { uint32_t macipdel_cnt; uint32_t prefixadd_cnt; uint32_t prefixdel_cnt; + uint32_t v4_nh_watch_add_cnt; + uint32_t v4_nh_watch_rem_cnt; + uint32_t v6_nh_watch_add_cnt; + uint32_t v6_nh_watch_rem_cnt; time_t nh_reg_time; time_t nh_dereg_time;