diff options
author | Ameya Dharkar <adharkar@vmware.com> | 2021-04-06 00:54:48 +0200 |
---|---|---|
committer | Ameya Dharkar <adharkar@vmware.com> | 2021-04-28 01:35:24 +0200 |
commit | d60f63f0872741921d192fa0e9b85d3c11982319 (patch) | |
tree | 105877e1abd2180a83d4f2a91965c0d0973bddb2 | |
parent | Merge pull request #8548 from donaldsharp/bgp_dampening (diff) | |
download | frr-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.c | 29 | ||||
-rw-r--r-- | bgpd/bgp_evpn_mh.c | 58 | ||||
-rw-r--r-- | bgpd/bgp_evpn_mh.h | 6 |
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); |