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)
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);
bgp_dest_unlock_node(global_dest);
}
+
+ delete_global_ead_evi_routes(bgp, vpn);
return 0;
}
* 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 */
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;
}
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"),
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
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);