From 5e9a493748681c8a28b02fe0a46818e1db95026a Mon Sep 17 00:00:00 2001 From: Rajasekar Raja Date: Thu, 15 Feb 2024 11:23:51 -0800 Subject: [PATCH] bgpd : backpressure - Handle BGP-Zebra(EPVN) Install evt Creation Current changes deals with EVPN routes installation to zebra. In evpn_route_select_install() we invoke evpn_zebra_install/uninstall which sends zclient_send_message(). Making similar changes as previous commit to handle evpn part of the code. Ticket: #3390099 Signed-off-by: Rajasekar Raja --- bgpd/bgp_evpn.c | 102 +++++++++++++++--------------- bgpd/bgp_evpn.h | 8 +++ bgpd/bgp_evpn_mh.c | 154 +++++++++++++++++++++++++++------------------ bgpd/bgp_evpn_mh.h | 10 +-- bgpd/bgp_route.c | 16 ++--- bgpd/bgp_table.h | 1 + bgpd/bgp_zebra.c | 60 ++++++++++++++---- bgpd/bgp_zebra.h | 2 +- 8 files changed, 218 insertions(+), 135 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 1a4364bb7460..e77a94aafba7 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -882,11 +882,10 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn, /* * Add (update) or delete MACIP from zebra. */ -static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p, - const struct ethaddr *mac, - struct in_addr remote_vtep_ip, int add, - uint8_t flags, uint32_t seq, esi_t *esi) +static enum zclient_send_status bgp_zebra_send_remote_macip( + struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p, + const struct ethaddr *mac, struct in_addr remote_vtep_ip, int add, + uint8_t flags, uint32_t seq, esi_t *esi) { struct stream *s; uint16_t ipa_len; @@ -894,8 +893,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, bool esi_valid; /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zclient or zclient->sock exists", + __func__); + return ZCLIENT_SEND_SUCCESS; + } /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { @@ -903,7 +906,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, zlog_debug( "%s: No zebra instance to talk to, not installing remote macip", __func__); - return 0; + return ZCLIENT_SEND_SUCCESS; } if (!esi) @@ -969,24 +972,26 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn, frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip, esi); - if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE) - return -1; - - return 0; + return zclient_send_message(zclient); } /* * Add (update) or delete remote VTEP from zebra. */ -static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p, - int flood_control, int add) +static enum zclient_send_status +bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, int flood_control, + int add) { struct stream *s; /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zclient or zclient->sock exists", + __func__); + return ZCLIENT_SEND_SUCCESS; + } /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { @@ -994,7 +999,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, zlog_debug( "%s: No zebra instance to talk to, not installing remote vtep", __func__); - return 0; + return ZCLIENT_SEND_SUCCESS; } s = zclient->obuf; @@ -1011,7 +1016,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, EC_BGP_VTEP_INVALID, "Bad remote IP when trying to %s remote VTEP for VNI %u", add ? "ADD" : "DEL", (vpn ? vpn->vni : 0)); - return -1; + return ZCLIENT_SEND_FAILURE; } stream_putl(s, flood_control); @@ -1024,10 +1029,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn, frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p); - if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE) - return -1; - - return 0; + return zclient_send_message(zclient); } /* @@ -1253,14 +1255,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr) } /* Install EVPN route into zebra. */ -static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p, - struct bgp_path_info *pi) +enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *pi) { - int ret; uint8_t flags; int flood_control = VXLAN_FLOOD_DISABLED; uint32_t seq; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { flags = 0; @@ -1338,6 +1340,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, flood_control = VXLAN_FLOOD_DISABLED; break; } + ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1); } @@ -1345,11 +1348,13 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn, } /* Uninstall EVPN route from zebra. */ -static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p, - struct bgp_path_info *pi, bool is_sync) +enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *pi, + bool is_sync) { - int ret; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) ret = bgp_zebra_send_remote_macip( @@ -1364,7 +1369,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p); else ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, - VXLAN_FLOOD_DISABLED, 0); + VXLAN_FLOOD_DISABLED, 0); return ret; } @@ -1456,11 +1461,9 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, && !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED) && !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) { if (bgp_zebra_has_route_changed(old_select)) - ret = evpn_zebra_install( - bgp, vpn, - (const struct prefix_evpn *)bgp_dest_get_prefix( - dest), - old_select); + bgp_zebra_route_install(dest, old_select, bgp, vpn, + true); + UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG); bgp_zebra_clear_route_change_flags(dest); @@ -1492,10 +1495,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, if (new_select && new_select->type == ZEBRA_ROUTE_BGP && (new_select->sub_type == BGP_ROUTE_IMPORTED || bgp_evpn_attr_is_sync(new_select->attr))) { - ret = evpn_zebra_install( - bgp, vpn, - (struct prefix_evpn *)bgp_dest_get_prefix(dest), - new_select); + bgp_zebra_route_install(dest, new_select, bgp, vpn, true); /* If an old best existed and it was a "local" route, the only * reason @@ -1514,11 +1514,8 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn, } else { if (old_select && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_IMPORTED) - ret = evpn_zebra_uninstall( - bgp, vpn, - (const struct prefix_evpn *)bgp_dest_get_prefix( - dest), - old_select, false); + bgp_zebra_route_install(dest, old_select, bgp, vpn, + false); } /* Clear any route change flags. */ @@ -2052,9 +2049,10 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp, if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP && (curr_select->sub_type == BGP_ROUTE_IMPORTED || bgp_evpn_attr_is_sync(curr_select->attr))) - evpn_zebra_install(bgp, vpn, - (const struct prefix_evpn *)bgp_dest_get_prefix(dest), - curr_select); + (void)evpn_zebra_install(bgp, vpn, + (const struct prefix_evpn *) + bgp_dest_get_prefix(dest), + curr_select); } /* @@ -2236,7 +2234,8 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn, */ new_is_sync = bgp_evpn_attr_is_sync(pi->attr); if (!new_is_sync && old_is_sync) - evpn_zebra_uninstall(bgp, vpn, p, pi, true); + (void)evpn_zebra_uninstall(bgp, vpn, p, pi, + true); } } bgp_path_info_unlock(pi); @@ -2503,7 +2502,8 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn, */ new_is_sync = bgp_evpn_attr_is_sync(pi->attr); if (!new_is_sync && old_is_sync) - evpn_zebra_uninstall(bgp, vpn, &evp, pi, true); + (void)evpn_zebra_uninstall(bgp, vpn, &evp, pi, + true); } } diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 840389758723..c163534fd867 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -183,4 +183,12 @@ extern bool bgp_evpn_mpath_has_dvni(const struct bgp *bgp_vrf, struct bgp_path_info *mpinfo); extern bool is_route_injectable_into_evpn(struct bgp_path_info *pi); +extern enum zclient_send_status evpn_zebra_install(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p, + struct bgp_path_info *pi); +extern enum zclient_send_status +evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p, struct bgp_path_info *pi, + bool is_sync); #endif /* _QUAGGA_BGP_EVPN_H */ diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index d88c52d1f6d9..75956ca8dc66 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -45,13 +45,14 @@ static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es); static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp, struct bgp_evpn_es *es); -static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, +static struct bgp_evpn_es_vtep * +bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es, + struct in_addr vtep_ip, bool esr, uint8_t df_alg, + uint16_t df_pref, int *zret); +static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp, struct bgp_evpn_es *es, struct in_addr vtep_ip, - bool esr, uint8_t df_alg, - uint16_t df_pref); -static void bgp_evpn_es_vtep_del(struct bgp *bgp, - struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr); + bool esr); static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es); static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es); static struct bgp_evpn_es_evi * @@ -94,6 +95,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, struct bgp_dest *dest) { int ret = 0; + int *zret = NULL; afi_t afi = AFI_L2VPN; safi_t safi = SAFI_EVPN; struct bgp_path_info *old_select; /* old best */ @@ -120,7 +122,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop, true /*esr*/, old_select->attr->df_alg, - old_select->attr->df_pref); + old_select->attr->df_pref, zret); } UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG); bgp_zebra_clear_route_change_flags(dest); @@ -149,7 +151,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp, && new_select->sub_type == BGP_ROUTE_IMPORTED) { bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop, true /*esr */, new_select->attr->df_alg, - new_select->attr->df_pref); + new_select->attr->df_pref, zret); } else { if (old_select && old_select->type == ZEBRA_ROUTE_BGP && old_select->sub_type == BGP_ROUTE_IMPORTED) @@ -1371,23 +1373,28 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es, } /* Send the remote ES to zebra for NHG programming */ -static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, - struct bgp_evpn_es_vtep *es_vtep, bool add) +static enum zclient_send_status +bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, + bool add) { struct bgp_evpn_es *es = es_vtep->es; struct stream *s; uint32_t flags = 0; /* Check socket. */ - if (!zclient || zclient->sock < 0) - return 0; + if (!zclient || zclient->sock < 0) { + if (BGP_DEBUG(zebra, ZEBRA)) + zlog_debug("%s: No zclient or zclient->sock exists", + __func__); + return ZCLIENT_SEND_SUCCESS; + } /* Don't try to register if Zebra doesn't know of this instance. */ if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) { if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("No zebra instance, not installing remote es %s", es->esi_str); - return 0; + return ZCLIENT_SEND_SUCCESS; } if (es_vtep->flags & BGP_EVPNES_VTEP_ESR) @@ -1418,12 +1425,12 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp, return zclient_send_message(zclient); } -static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, - struct bgp_evpn_es_vtep *es_vtep, - bool param_change) +static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active( + struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, bool param_change) { bool old_active; bool new_active; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE); /* currently we need an active EVI reference to use the VTEP as @@ -1445,7 +1452,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, es_vtep->df_alg, es_vtep->df_pref); /* send remote ES to zebra */ - bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active); + ret = bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active); /* The NHG is updated first for efficient failover handling. * Note the NHG can be de-activated while there are bgp @@ -1457,13 +1464,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp, /* queue up the es for background consistency checks */ bgp_evpn_es_cons_checks_pend_add(es_vtep->es); } + + return ret; } -static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, - struct bgp_evpn_es *es, - struct in_addr vtep_ip, - bool esr, uint8_t df_alg, - uint16_t df_pref) +static struct bgp_evpn_es_vtep * +bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es, + struct in_addr vtep_ip, bool esr, uint8_t df_alg, + uint16_t df_pref, int *zret) { struct bgp_evpn_es_vtep *es_vtep; bool param_change = false; @@ -1490,15 +1498,17 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp, ++es_vtep->evi_cnt; } - bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); + *zret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); return es_vtep; } -static void bgp_evpn_es_vtep_do_del(struct bgp *bgp, - struct bgp_evpn_es_vtep *es_vtep, bool esr) +static enum zclient_send_status +bgp_evpn_es_vtep_do_del(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, + bool esr) { bool param_change = false; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str, @@ -1515,18 +1525,25 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp, --es_vtep->evi_cnt; } - bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); + ret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change); bgp_evpn_es_vtep_free(es_vtep); + + return ret; } -static void bgp_evpn_es_vtep_del(struct bgp *bgp, - struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr) +static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp, + struct bgp_evpn_es *es, + struct in_addr vtep_ip, + bool esr) { struct bgp_evpn_es_vtep *es_vtep; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip); if (es_vtep) - bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr); + ret = bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr); + + return ret; } /********************** ES MAC-IP paths ************************************* @@ -3399,12 +3416,15 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find( /* A VTEP can be added as "active" attach to an ES if EAD-per-ES and * EAD-per-EVI routes are rxed from it. */ -static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, - struct bgp_evpn_es_evi_vtep *evi_vtep) +static enum zclient_send_status +bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, + struct bgp_evpn_es_evi_vtep *evi_vtep) { bool old_active; bool new_active; uint32_t ead_activity_flags; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; + int *zret = NULL; old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE); @@ -3425,7 +3445,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE); if (old_active == new_active) - return; + return ret; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("es %s evi %u vtep %pI4 %s", @@ -3434,24 +3454,28 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp, new_active ? "active" : "inactive"); /* add VTEP to parent es */ - if (new_active) - evi_vtep->es_vtep = bgp_evpn_es_vtep_add( - bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip, - false /*esr*/, 0, 0); - else { + if (new_active) { + evi_vtep->es_vtep = + bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es, + evi_vtep->vtep_ip, false /*esr*/, + 0, 0, zret); + ret = *zret; + } else { if (evi_vtep->es_vtep) { - bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep, - false /*esr*/); + ret = bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep, + false /*esr*/); evi_vtep->es_vtep = NULL; } } /* queue up the parent es for background consistency checks */ bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es); + + return ret; } -static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp, - struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, - bool ead_es) +static enum zclient_send_status +bgp_evpn_es_evi_vtep_add(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi, + struct in_addr vtep_ip, bool ead_es) { struct bgp_evpn_es_evi_vtep *evi_vtep; @@ -3475,18 +3499,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp, else SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI); - bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); + return bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); } -static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp, - struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip, - bool ead_es) +static enum zclient_send_status +bgp_evpn_es_evi_vtep_del(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi, + struct in_addr vtep_ip, bool ead_es) { struct bgp_evpn_es_evi_vtep *evi_vtep; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip); if (!evi_vtep) - return; + return ret; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("del es %s evi %u vtep %pI4 %s", @@ -3503,8 +3528,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp, else UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI); - bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); + ret = bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep); bgp_evpn_es_evi_vtep_free(evi_vtep); + + return ret; } /* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */ @@ -3780,18 +3807,20 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni) /* Add remote ES-EVI entry. This is actually the remote VTEP add and the * ES-EVI is implicity created on first VTEP's reference. */ -int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p) +enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p) { char buf[ESI_STR_LEN]; struct bgp_evpn_es *es; struct bgp_evpn_es_evi *es_evi; bool ead_es; const esi_t *esi = &p->prefix.ead_addr.esi; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; if (!vpn) /* local EAD-ES need not be sent back to zebra */ - return 0; + return ret; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug("add remote %s es %s evi %u vtep %pI4", @@ -3808,27 +3837,29 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, es_evi = bgp_evpn_es_evi_new(es, vpn); ead_es = !!p->prefix.ead_addr.eth_tag; - bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, - ead_es); + ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi, + p->prefix.ead_addr.ip.ipaddr_v4, ead_es); bgp_evpn_es_evi_remote_info_re_eval(es_evi); - return 0; + return ret; } /* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the * parent es-evi freed up implicitly in last VTEP's deref. */ -int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p) +enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp, + struct bgpevpn *vpn, + const struct prefix_evpn *p) { char buf[ESI_STR_LEN]; struct bgp_evpn_es *es; struct bgp_evpn_es_evi *es_evi; bool ead_es; + enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS; if (!vpn) /* local EAD-ES need not be sent back to zebra */ - return 0; + return ret; if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) zlog_debug( @@ -3847,7 +3878,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, esi_to_str(&p->prefix.ead_addr.esi, buf, sizeof(buf)), vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4); - return 0; + return ret; } es_evi = bgp_evpn_es_evi_find(es, vpn); if (!es_evi) { @@ -3860,14 +3891,15 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, sizeof(buf)), vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4); - return 0; + return ret; } ead_es = !!p->prefix.ead_addr.eth_tag; - bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4, - ead_es); + ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi, + p->prefix.ead_addr.ip.ipaddr_v4, ead_es); bgp_evpn_es_evi_remote_info_re_eval(es_evi); - return 0; + + return ret; } /* If a VNI is being deleted we need to force del all remote VTEPs */ diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index cebabb9fd051..5d393c37a20d 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -418,10 +418,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi, extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi); extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni); extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni); -extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p); -extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, - const struct prefix_evpn *p); +extern enum zclient_send_status +bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p); +extern enum zclient_send_status +bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn, + const struct prefix_evpn *p); extern void bgp_evpn_mh_init(void); extern void bgp_evpn_mh_finish(void); void bgp_evpn_vni_es_init(struct bgpevpn *vpn); diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 58e5be7825d9..56186fbfa86e 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3406,8 +3406,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || new_select->sub_type == BGP_ROUTE_IMPORTED)) - bgp_zebra_route_install(dest, old_select, - bgp, true); + bgp_zebra_route_install(dest, + old_select, bgp, + NULL, true); } } @@ -3525,9 +3526,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, if (old_select && is_route_parent_evpn(old_select)) bgp_zebra_route_install(dest, old_select, bgp, - false); + NULL, false); - bgp_zebra_route_install(dest, new_select, bgp, true); + bgp_zebra_route_install(dest, new_select, bgp, NULL, + true); } else { /* Withdraw the route from the kernel. */ if (old_select && old_select->type == ZEBRA_ROUTE_BGP @@ -3536,7 +3538,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest, || old_select->sub_type == BGP_ROUTE_IMPORTED)) bgp_zebra_route_install(dest, old_select, bgp, - false); + NULL, false); } } @@ -4433,7 +4435,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)) /* remove from RIB previous entry */ - bgp_zebra_route_install(dest, pi, bgp, false); + bgp_zebra_route_install(dest, pi, bgp, NULL, false); } if (peer->sort == BGP_PEER_EBGP) { @@ -6060,7 +6062,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table, if (bgp_fibupd_safi(safi)) bgp_zebra_route_install(dest, pi, bgp, - false); + NULL, false); } dest = bgp_path_info_reap(dest, pi); diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index 95705d24707d..7851bdfbc8df 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -78,6 +78,7 @@ struct bgp_dest { struct zebra_announce_item zai; struct bgp_path_info *za_bgp_pi; + struct bgpevpn *za_vpn; uint64_t version; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 57e94e33e1e8..b34f1f93da82 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1675,7 +1675,8 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi) && (pi->sub_type == BGP_ROUTE_NORMAL || pi->sub_type == BGP_ROUTE_IMPORTED))) - bgp_zebra_route_install(dest, pi, bgp, true); + bgp_zebra_route_install(dest, pi, bgp, NULL, + true); } /* Announce routes of any bgp subtype of a table to zebra */ @@ -1697,7 +1698,8 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi, for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && pi->type == ZEBRA_ROUTE_BGP) - bgp_zebra_route_install(dest, pi, bgp, true); + bgp_zebra_route_install(dest, pi, bgp, NULL, + true); } static enum zclient_send_status @@ -1750,8 +1752,11 @@ bgp_zebra_withdraw_actual(struct bgp_dest *dest, struct bgp_path_info *info, #define ZEBRA_LOOP 1000 static void bgp_handle_route_announcements_to_zebra(struct event *e) { + bool is_evpn = false; uint32_t count = 0; struct bgp_dest *dest = NULL; + const struct prefix *pfx = NULL; + const struct prefix_evpn *evpn_pfx = NULL; struct bgp_table *bgp_tbl = NULL; enum zclient_send_status status = ZCLIENT_SEND_SUCCESS; @@ -1761,21 +1766,45 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e) if (!dest) break; + pfx = bgp_dest_get_prefix(dest); + if (pfx->family == AF_EVPN) { + is_evpn = true; + evpn_pfx = (const struct prefix_evpn *)pfx; + } + bgp_tbl = bgp_dest_table(dest); if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL)) { - status = bgp_zebra_announce_actual(dest, dest->za_bgp_pi, - bgp_tbl->bgp); + if (is_evpn) + status = evpn_zebra_install(bgp_tbl->bgp, + dest->za_vpn, + evpn_pfx, + dest->za_bgp_pi); + else + status = + bgp_zebra_announce_actual(dest, + dest->za_bgp_pi, + bgp_tbl->bgp); UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) { - status = bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, - bgp_tbl->bgp); + if (is_evpn) + status = evpn_zebra_uninstall(bgp_tbl->bgp, + dest->za_vpn, + evpn_pfx, + dest->za_bgp_pi, + false); + else + status = + bgp_zebra_withdraw_actual(dest, + dest->za_bgp_pi, + bgp_tbl->bgp); UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE); } bgp_path_info_unlock(dest->za_bgp_pi); dest->za_bgp_pi = NULL; + dest->za_vpn = NULL; bgp_dest_unlock_node(dest); if (status == ZCLIENT_SEND_BUFFERED) @@ -1829,8 +1858,13 @@ static void bgp_zebra_buffer_write_ready(void) * withdrawn. */ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, - struct bgp *bgp, bool install) + struct bgp *bgp, struct bgpevpn *vpn, bool install) { + const struct prefix *pfx = NULL; + bool is_evpn; + + pfx = bgp_dest_get_prefix(dest); + is_evpn = pfx->family == AF_EVPN ? true : false; /* * BGP is installing this route and bgp has been configured * to suppress announcements until the route has been installed @@ -1840,7 +1874,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, if (BGP_SUPPRESS_FIB_ENABLED(bgp)) SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); - if (bgp->main_zebra_update_hold) + if (bgp->main_zebra_update_hold && !is_evpn) return; } else { UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING); @@ -1850,7 +1884,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, * Don't try to install if we're not connected to Zebra or Zebra doesn't * know of this instance. */ - if (!bgp_install_info_to_zebra(bgp)) + if (!bgp_install_info_to_zebra(bgp) && !is_evpn) return; if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) && @@ -1870,7 +1904,7 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, dest->za_bgp_pi = info; } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) { assert(dest->za_bgp_pi); - if (install) + if (install & !is_evpn) bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp); bgp_path_info_unlock(dest->za_bgp_pi); @@ -1878,6 +1912,9 @@ void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info, dest->za_bgp_pi = info; } + if (is_evpn) + dest->za_vpn = vpn; + if (install) { UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE); SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL); @@ -1908,7 +1945,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) { if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) && (pi->type == ZEBRA_ROUTE_BGP)) - bgp_zebra_route_install(dest, pi, bgp, false); + bgp_zebra_route_install(dest, pi, bgp, NULL, + false); } } } diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h index 6d3bdce10825..b58196072eaf 100644 --- a/bgpd/bgp_zebra.h +++ b/bgpd/bgp_zebra.h @@ -30,7 +30,7 @@ extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size, extern int bgp_if_update_all(void); extern void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *path, struct bgp *bgp, - bool install); + struct bgpevpn *vpn, bool install); extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi); /* Announce routes of any bgp subtype of a table to zebra */