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().

This is a continuation of code changes (similar to
ccfe452763) but to handle evpn part
of the code.

Ticket: #3390099

Signed-off-by: Rajasekar Raja <rajasekarr@nvidia.com>
This commit is contained in:
Rajasekar Raja 2024-02-15 11:23:51 -08:00
parent 498967799d
commit a07df6f754
9 changed files with 300 additions and 142 deletions

View File

@ -892,11 +892,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;
@ -904,8 +903,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)) {
@ -913,7 +916,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)
@ -979,24 +982,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)) {
@ -1004,7 +1009,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;
@ -1021,7 +1026,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);
@ -1034,10 +1039,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);
}
/*
@ -1263,14 +1265,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;
@ -1348,6 +1350,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);
}
@ -1355,11 +1358,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(
@ -1374,7 +1379,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;
}
@ -1465,12 +1470,18 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
&& !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
&& !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);
if (bgp_zebra_has_route_changed(old_select)) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
evpn_zebra_install(bgp, vpn,
(const struct prefix_evpn *)
bgp_dest_get_prefix(
dest),
old_select);
else
bgp_zebra_route_install(dest, old_select, bgp,
true, vpn, false);
}
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);
@ -1502,10 +1513,14 @@ 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);
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
evpn_zebra_install(bgp, vpn,
(const struct prefix_evpn *)
bgp_dest_get_prefix(dest),
new_select);
else
bgp_zebra_route_install(dest, new_select, bgp, true,
vpn, false);
/* If an old best existed and it was a "local" route, the only
* reason
@ -1522,13 +1537,19 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
evpn_delete_old_local_route(bgp, vpn, dest,
old_select, new_select);
} 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);
if (old_select && old_select->type == ZEBRA_ROUTE_BGP &&
old_select->sub_type == BGP_ROUTE_IMPORTED) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
CHECK_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN))
evpn_zebra_uninstall(bgp, vpn,
(const struct prefix_evpn *)
bgp_dest_get_prefix(
dest),
old_select, false);
else
bgp_zebra_route_install(dest, old_select, bgp,
false, vpn, false);
}
}
/* Clear any route change flags. */
@ -2062,9 +2083,19 @@ 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);
if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
(curr_select->sub_type == BGP_ROUTE_IMPORTED ||
bgp_evpn_attr_is_sync(curr_select->attr))) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
evpn_zebra_install(bgp, vpn,
(const struct prefix_evpn *)
bgp_dest_get_prefix(
dest),
curr_select);
else
bgp_zebra_route_install(dest, curr_select, bgp,
true, vpn, false);
}
}
/*
@ -2245,8 +2276,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
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);
if (!new_is_sync && old_is_sync) {
if (CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
evpn_zebra_uninstall(bgp, vpn, p, pi,
true);
else
bgp_zebra_route_install(dest, pi, bgp,
false, vpn,
true);
}
}
}
bgp_path_info_unlock(pi);
@ -2512,8 +2551,17 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
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);
if (!new_is_sync && old_is_sync) {
if (CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
(void)evpn_zebra_uninstall(bgp, vpn,
&evp, pi,
true);
else
bgp_zebra_route_install(dest, pi, bgp,
false, vpn,
true);
}
}
}
@ -2795,7 +2843,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
delete_all_type2_routes(bgp, vpn);
build_evpn_type3_prefix(&p, vpn->originator_ip);
/*
* To handle the following scenario:
* - Say, the new zebra announce fifo list has few vni Evpn prefixes yet
* to be sent to zebra.
* - At this point if we have triggers like "no advertise-all-vni" or
* "networking restart", where a vni is going down.
*
* Perform the below
* 1) send withdraw routes to zebra immediately in case it is installed.
* 2) before we blow up the vni table, we need to walk the list and
* pop all the dest whose za_vpn points to this vni.
*/
SET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
ret = delete_evpn_route(bgp, vpn, &p);
UNSET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
if (ret)
return ret;
@ -6262,6 +6325,17 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
*/
void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
{
struct bgp_dest *dest = NULL;
while (zebra_announce_count(&bm->zebra_announce_head)) {
dest = zebra_announce_pop(&bm->zebra_announce_head);
if (dest->za_vpn == vpn) {
bgp_path_info_unlock(dest->za_bgp_pi);
bgp_dest_unlock_node(dest);
} else
zebra_announce_add_tail(&bm->zebra_announce_head, dest);
}
bgp_evpn_remote_ip_hash_destroy(vpn);
bgp_evpn_vni_es_cleanup(vpn);
bgpevpn_unlink_from_l3vni(vpn);

View File

@ -186,4 +186,12 @@ extern bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi);
extern void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi,
safi_t safi);
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 */

View File

@ -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 = 0;
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)
@ -447,7 +449,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr->mp_nexthop_global_in);
}
/* Return back the route entry. */
/* Return back th*e route entry. */
*ri = tmp_pi;
return 0;
}
@ -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,14 @@ 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;
old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
@ -3425,7 +3444,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 +3453,27 @@ 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, &ret);
} 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 +3497,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 +3526,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 +3805,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 +3835,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 +3876,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 +3889,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 */

View File

@ -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);

View File

@ -3402,9 +3402,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type
== BGP_ROUTE_IMPORTED))
bgp_zebra_route_install(dest, old_select,
bgp, true);
bgp, true, NULL,
false);
}
}
@ -3522,9 +3522,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);
false, NULL, false);
bgp_zebra_route_install(dest, new_select, bgp, true);
bgp_zebra_route_install(dest, new_select, bgp, true,
NULL, false);
} else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@ -3533,7 +3534,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);
false, NULL, false);
}
}
@ -4430,7 +4431,8 @@ 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, false, NULL,
false);
}
if (peer->sort == BGP_PEER_EBGP) {

View File

@ -78,6 +78,8 @@ struct bgp_dest {
struct zebra_announce_item zai;
struct bgp_path_info *za_bgp_pi;
struct bgpevpn *za_vpn;
bool za_is_sync;
uint64_t version;

View File

@ -1687,12 +1687,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
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
&& (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, true,
NULL, false);
}
/* Announce routes of any bgp subtype of a table to zebra */
@ -1714,7 +1713,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, true,
NULL, false);
}
enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
@ -1767,6 +1767,7 @@ enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
#define ZEBRA_ANNOUNCEMENTS_LIMIT 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;
struct bgp_table *table = NULL;
@ -1781,6 +1782,8 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
table = bgp_dest_table(dest);
install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
is_evpn = true;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
@ -1788,17 +1791,38 @@ static void bgp_handle_route_announcements_to_zebra(struct event *e)
table->bgp->name_pretty, dest, dest->flags);
if (install) {
status = bgp_zebra_announce_actual(dest, dest->za_bgp_pi,
table->bgp);
if (is_evpn)
status =
evpn_zebra_install(table->bgp,
dest->za_vpn,
(const struct prefix_evpn
*)
bgp_dest_get_prefix(
dest),
dest->za_bgp_pi);
else
status = bgp_zebra_announce_actual(dest,
dest->za_bgp_pi,
table->bgp);
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
} else {
status = bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi,
table->bgp);
if (is_evpn)
status = evpn_zebra_uninstall(
table->bgp, dest->za_vpn,
(const struct prefix_evpn *)
bgp_dest_get_prefix(dest),
dest->za_bgp_pi, false);
else
status = bgp_zebra_withdraw_actual(dest,
dest->za_bgp_pi,
table->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)
@ -1852,8 +1876,16 @@ 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, bool install, struct bgpevpn *vpn,
bool is_sync)
{
bool is_evpn = false;
struct bgp_table *table = NULL;
table = bgp_dest_table(dest);
if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
is_evpn = true;
/*
* BGP is installing this route and bgp has been configured
* to suppress announcements until the route has been installed
@ -1863,7 +1895,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);
@ -1873,7 +1905,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) &&
@ -1893,7 +1925,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);
@ -1901,6 +1933,11 @@ 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;
dest->za_is_sync = is_sync;
}
if (install) {
UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
@ -1931,7 +1968,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, false,
NULL, false);
}
}
}

View File

@ -30,7 +30,8 @@ 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);
bool install, struct bgpevpn *vpn,
bool is_sync);
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 */

View File

@ -530,6 +530,7 @@ struct bgp {
#define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35)
#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
#define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
#define BGP_FLAG_VNI_DOWN (1ULL << 38)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.