From ec0ab5443f5d51e452a174cee5a078738b4d7bf7 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Mon, 14 Jan 2019 15:24:43 -0800 Subject: [PATCH] bgpd: reinstate current bgp best route on an inactive neigh del When an inactive-neigh delete is rxed bgp will not have a local path to remove (and re-run path selection). Instead it simply re-installs the current best remote path if any. Ticket: CM-23018 Testing Done: evpn-min Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_evpn.c | 50 ++++++++++++++++++++++++++++++++---------------- bgpd/bgp_evpn.h | 3 ++- bgpd/bgp_vty.c | 3 ++- bgpd/bgp_zebra.c | 10 +++++++--- 4 files changed, 44 insertions(+), 22 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 7e2fa9ea76..c74d7829bd 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1685,6 +1685,27 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, return route_change; } +static void evpn_zebra_reinstall_best_route(struct bgp *bgp, + struct bgpevpn *vpn, struct bgp_node *rn) +{ + struct bgp_path_info *tmp_ri; + struct bgp_path_info *curr_select = NULL; + + for (tmp_ri = bgp_node_get_bgp_path_info(rn); + tmp_ri; tmp_ri = tmp_ri->next) { + if (CHECK_FLAG(tmp_ri->flags, BGP_PATH_SELECTED)) { + curr_select = tmp_ri; + break; + } + } + + if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP + && curr_select->sub_type == BGP_ROUTE_IMPORTED) + evpn_zebra_install(bgp, vpn, + (struct prefix_evpn *)&rn->p, + curr_select); +} + /* * If the local route was not selected evict it and tell zebra to re-add * the best remote dest. @@ -1704,8 +1725,6 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp, struct bgp_node *rn, struct bgp_path_info *local_pi) { - struct bgp_path_info *tmp_pi; - struct bgp_path_info *curr_select = NULL; char buf[PREFIX_STRLEN]; /* local path was not picked as the winner; kick it out */ @@ -1717,18 +1736,7 @@ static void evpn_cleanup_local_non_best_route(struct bgp *bgp, bgp_path_info_reap(rn, local_pi); /* tell zebra to re-add the best remote path */ - for (tmp_pi = bgp_node_get_bgp_path_info(rn); - tmp_pi; tmp_pi = tmp_pi->next) { - if (CHECK_FLAG(tmp_pi->flags, BGP_PATH_SELECTED)) { - curr_select = tmp_pi; - break; - } - } - if (curr_select && - curr_select->type == ZEBRA_ROUTE_BGP - && curr_select->sub_type == BGP_ROUTE_IMPORTED) - evpn_zebra_install(bgp, vpn, (struct prefix_evpn *)&rn->p, - curr_select); + evpn_zebra_reinstall_best_route(bgp, vpn, rn); } /* @@ -5304,10 +5312,11 @@ int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp) * Handle del of a local MACIP. */ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, - struct ipaddr *ip) + struct ipaddr *ip, int state) { struct bgpevpn *vpn; struct prefix_evpn p; + struct bgp_node *rn; /* Lookup VNI hash - should exist. */ vpn = bgp_evpn_lookup_vni(bgp, vni); @@ -5318,9 +5327,16 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac, return -1; } - /* Remove EVPN type-2 route and schedule for processing. */ build_evpn_type2_prefix(&p, mac, ip); - delete_evpn_route(bgp, vpn, &p); + if (state == ZEBRA_NEIGH_ACTIVE) { + /* Remove EVPN type-2 route and schedule for processing. */ + delete_evpn_route(bgp, vpn, &p); + } else { + /* Re-instate the current remote best path if any */ + rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p); + if (rn) + evpn_zebra_reinstall_best_route(bgp, vpn, rn); + } return 0; } diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 8728fdcab7..5c3d4ce3aa 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -129,7 +129,8 @@ extern int bgp_evpn_unimport_route(struct bgp *bgp, afi_t afi, safi_t safi, struct prefix *p, struct bgp_path_info *ri); extern int bgp_filter_evpn_routes_upon_martian_nh_change(struct bgp *bgp); extern int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, - struct ethaddr *mac, struct ipaddr *ip); + struct ethaddr *mac, struct ipaddr *ip, + int state); extern int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac, struct ipaddr *ip, uint8_t flags, uint32_t seq); diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index c6e48cc160..2da19b28db 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -22,6 +22,7 @@ #include "command.h" #include "lib/json.h" +#include "lib/zclient.h" #include "prefix.h" #include "plist.h" #include "buffer.h" @@ -897,7 +898,7 @@ DEFUN_HIDDEN (no_bgp_local_mac, return CMD_WARNING; } - rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); + rv = bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, ZEBRA_NEIGH_ACTIVE); if (rv < 0) { vty_out(vty, "Internal error\n"); return CMD_WARNING; diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 3c4b219466..17de943381 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -2480,6 +2480,7 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, char buf1[INET6_ADDRSTRLEN]; uint8_t flags = 0; uint32_t seqnum = 0; + int state = 0; memset(&ip, 0, sizeof(ip)); s = zclient->ibuf; @@ -2503,6 +2504,8 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, if (command == ZEBRA_MACIP_ADD) { flags = stream_getc(s); seqnum = stream_getl(s); + } else { + state = stream_getl(s); } bgp = bgp_lookup_by_vrf_id(vrf_id); @@ -2510,16 +2513,17 @@ static int bgp_zebra_process_local_macip(int command, struct zclient *zclient, return 0; if (BGP_DEBUG(zebra, ZEBRA)) - zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u", + zlog_debug("%u:Recv MACIP %s flags 0x%x MAC %s IP %s VNI %u seq %u state %d", vrf_id, (command == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags, prefix_mac2str(&mac, buf, sizeof(buf)), - ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum); + ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum, + state); if (command == ZEBRA_MACIP_ADD) return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip, flags, seqnum); else - return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip); + return bgp_evpn_local_macip_del(bgp, vni, &mac, &ip, state); } static void bgp_zebra_process_local_ip_prefix(int cmd, struct zclient *zclient, -- 2.39.5