summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmeya Dharkar <adharkar@vmware.com>2021-04-06 00:54:48 +0200
committerAmeya Dharkar <adharkar@vmware.com>2021-04-28 01:35:24 +0200
commitd60f63f0872741921d192fa0e9b85d3c11982319 (patch)
tree105877e1abd2180a83d4f2a91965c0d0973bddb2
parentMerge pull request #8548 from donaldsharp/bgp_dampening (diff)
downloadfrr-d60f63f0872741921d192fa0e9b85d3c11982319.tar.xz
frr-d60f63f0872741921d192fa0e9b85d3c11982319.zip
bgpd: Handle EAD/EVI local route updates on VNI RD change
When VNI RD changes, EAD/EVI routes with old RD should be withdrawn from the global routing table and EAD/EVI routes in the VNI should be advertised with the new RD. Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
-rw-r--r--bgpd/bgp_evpn.c29
-rw-r--r--bgpd/bgp_evpn_mh.c58
-rw-r--r--bgpd/bgp_evpn_mh.h6
3 files changed, 81 insertions, 12 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 2d4fea413..0d62f26d7 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -3561,8 +3561,12 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
const struct prefix_evpn *evp =
(const struct prefix_evpn *)bgp_dest_get_prefix(dest);
- /* Identify MAC-IP local routes. */
- if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
+ /*
+ * We have already processed type-3 routes.
+ * Process only type-1 and type-2 routes here.
+ */
+ if (evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE
+ && evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@@ -3580,10 +3584,23 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
evp, &vpn->prd);
assert(global_dest);
- update_evpn_route_entry(bgp, vpn, afi, safi, global_dest, attr, 1,
- &global_pi, 0,
- mac_mobility_seqnum(attr),
+
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+ /* Type-2 route */
+ update_evpn_route_entry(
+ bgp, vpn, afi, safi, global_dest, attr, 1,
+ &global_pi, 0, mac_mobility_seqnum(attr),
false /* setup_sync */, NULL /* old_is_sync */);
+ } else {
+ /* Type-1 route */
+ struct bgp_evpn_es *es;
+ int route_changed = 0;
+
+ es = bgp_evpn_es_find(&evp->prefix.ead_addr.esi);
+ bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi,
+ global_dest, attr, 1,
+ &global_pi, &route_changed);
+ }
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_dest, afi, safi);
@@ -3629,6 +3646,8 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
bgp_dest_unlock_node(global_dest);
}
+
+ delete_global_ead_evi_routes(bgp, vpn);
return 0;
}
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 6467ff8a2..59bced6f9 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -347,11 +347,10 @@ static void bgp_evpn_es_route_del_all(struct bgp *bgp, struct bgp_evpn_es *es)
* Note: vpn is applicable only to EAD-EVI routes (NULL for EAD-ES and
* ESR).
*/
-static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
- struct bgpevpn *vpn, afi_t afi, safi_t safi,
- struct bgp_dest *dest, struct attr *attr,
- int add, struct bgp_path_info **ri,
- int *route_changed)
+int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct bgpevpn *vpn, afi_t afi, safi_t safi,
+ struct bgp_dest *dest, struct attr *attr, int add,
+ struct bgp_path_info **ri, int *route_changed)
{
struct bgp_path_info *tmp_pi = NULL;
struct bgp_path_info *local_pi = NULL; /* local route entry if any */
@@ -384,7 +383,8 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
flog_err(
EC_BGP_ES_INVALID,
"%u ERROR: local es route for ESI: %s Vtep %pI4 also learnt from remote",
- bgp->vrf_id, es->esi_str, &es->originator_ip);
+ bgp->vrf_id, es ? es->esi_str : "Null",
+ &es->originator_ip);
return -1;
}
@@ -441,7 +441,7 @@ static int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
zlog_debug(
"local ES %s vni %u route-type %s nexthop %pI4 updated",
- es->esi_str, vpn ? vpn->vni : 0,
+ es ? es->esi_str : "Null", vpn ? vpn->vni : 0,
evp->prefix.route_type == BGP_EVPN_ES_ROUTE
? "esr"
: (vpn ? "ead-evi" : "ead-es"),
@@ -524,6 +524,50 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
return 0;
}
+/*
+ * This function is called when the VNI RD changes.
+ * Delete all EAD/EVI local routes for this VNI from the global routing table.
+ * These routes are scheduled for withdraw from peers.
+ */
+int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
+{
+ afi_t afi;
+ safi_t safi;
+ struct bgp_dest *rdrn, *rn;
+ struct bgp_table *table;
+ struct bgp_path_info *pi;
+
+ afi = AFI_L2VPN;
+ safi = SAFI_EVPN;
+
+ /* Find the RD node for the VNI in the global table */
+ rdrn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)&vpn->prd);
+ if (rdrn && bgp_dest_has_bgp_path_info_data(rdrn)) {
+ table = bgp_dest_get_bgp_table_info(rdrn);
+
+ /*
+ * Iterate over all the routes in this table and delete EAD/EVI
+ * routes
+ */
+ for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
+ struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
+
+ if (evp->prefix.route_type != BGP_EVPN_AD_ROUTE)
+ continue;
+
+ delete_evpn_route_entry(bgp, afi, safi, rn, &pi);
+ if (pi)
+ bgp_process(bgp, rn, afi, safi);
+ }
+ }
+
+ /* Unlock RD node. */
+ if (rdrn)
+ bgp_dest_unlock_node(rdrn);
+
+ return 0;
+}
+
/*****************************************************************************
* Ethernet Segment (Type-4) Routes
* ESRs are used for DF election. Currently service-carving described in
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index c96de8687..22a421566 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -377,6 +377,12 @@ extern int bgp_evpn_es_route_install_uninstall(struct bgp *bgp,
struct prefix_evpn *evp, struct bgp_path_info *pi,
int install);
extern void update_type1_routes_for_evi(struct bgp *bgp, struct bgpevpn *vpn);
+extern int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn);
+extern int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct bgpevpn *vpn, afi_t afi, safi_t safi,
+ struct bgp_dest *dest, struct attr *attr,
+ int add, struct bgp_path_info **ri,
+ int *route_changed);
int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi,
struct attr *attr, uint8_t *pfx, int psize,
uint32_t addpath_id);