Skip to content

Commit

Permalink
bgpd : backpressure - Handle BGP-Zebra(EPVN) Install evt Creation
Browse files Browse the repository at this point in the history
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
ccfe452) but to handle evpn part
of the code.

Ticket: #3390099

Signed-off-by: Rajasekar Raja <[email protected]>
  • Loading branch information
raja-rajasekar committed Mar 27, 2024
1 parent 4989677 commit e755c6e
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 142 deletions.
191 changes: 135 additions & 56 deletions bgpd/bgp_evpn.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,28 +892,31 @@ 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;
static struct in_addr zero_remote_vtep_ip;
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)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
"%s: No zebra instance to talk to, not installing remote macip",
__func__);
return 0;
return ZCLIENT_SEND_SUCCESS;
}

if (!esi)
Expand Down Expand Up @@ -979,32 +982,34 @@ 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)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
"%s: No zebra instance to talk to, not installing remote vtep",
__func__);
return 0;
return ZCLIENT_SEND_SUCCESS;
}

s = zclient->obuf;
Expand All @@ -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);

Expand All @@ -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);
}

/*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1348,18 +1350,21 @@ 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);
}

return ret;
}

/* 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(
Expand All @@ -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;
}
Expand Down Expand Up @@ -1465,12 +1470,19 @@ 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))
(void)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);
Expand Down Expand Up @@ -1502,10 +1514,15 @@ 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))
(void)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
Expand All @@ -1522,13 +1539,21 @@ 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)))
(void)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. */
Expand Down Expand Up @@ -2062,9 +2087,20 @@ 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))
(void)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);
}
}

/*
Expand Down Expand Up @@ -2245,8 +2281,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))
(void)evpn_zebra_uninstall(bgp, vpn, p,
pi, true);
else
bgp_zebra_route_install(dest, pi, bgp,
false, vpn,
true);
}
}
}
bgp_path_info_unlock(pi);
Expand Down Expand Up @@ -2512,8 +2556,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);
}
}
}

Expand Down Expand Up @@ -2795,7 +2848,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;

Expand Down Expand Up @@ -6262,6 +6330,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);
Expand Down
8 changes: 8 additions & 0 deletions bgpd/bgp_evpn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Loading

0 comments on commit e755c6e

Please sign in to comment.