]> git.puffer.fish Git - matthieu/frr.git/commitdiff
bgpd: Handle EAD/EVI local route updates on VNI RD change
authorAmeya Dharkar <adharkar@vmware.com>
Mon, 5 Apr 2021 22:54:48 +0000 (15:54 -0700)
committerAmeya Dharkar <adharkar@vmware.com>
Tue, 27 Apr 2021 23:35:24 +0000 (16:35 -0700)
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>
bgpd/bgp_evpn.c
bgpd/bgp_evpn_mh.c
bgpd/bgp_evpn_mh.h

index 2d4fea413a1a4f1fc9c189d5f6ac55edd0decd0f..0d62f26d7cae77ab5a2aa2fa1a00f45bc9f6ac6b 100644 (file)
@@ -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;
 }
 
index 6467ff8a283c97c1af0f9ac2bd1c152308a2adef..59bced6f93a177f6094ed7fa0269c32d2f3fb4a3 100644 (file)
@@ -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
index c96de8687159895b3e05a32f89be9f1f002b9630..22a42156641d4d9b93fe5c001f3aa3abf9e485d7 100644 (file)
@@ -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);