diff options
| author | Anuradha Karuppiah <anuradhak@cumulusnetworks.com> | 2020-05-08 19:36:47 -0700 | 
|---|---|---|
| committer | Anuradha Karuppiah <anuradhak@nvidia.com> | 2020-11-24 11:06:08 -0800 | 
| commit | 26c03e43fba0c1fe673f3fe574e0de560f466eac (patch) | |
| tree | bb24a49d4cf48cd3e1e90d511286c2590eb2bb24 | |
| parent | c589d84746d96c1714582e437eb9cec691795252 (diff) | |
bgpd: Handle ES VTEP add/del to a host route
1. MAC-IP routes in the VPN routing table are linked to the
destination ES for efficient handling for remote ES link flaps.
2. Only MAC-IP paths whose nexthops are active (added via EAD-ES)
are imported into the VRF routing table.
Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
| -rw-r--r-- | bgpd/bgp_evpn.c | 119 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.c | 188 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_mh.h | 10 | ||||
| -rw-r--r-- | bgpd/bgp_evpn_private.h | 9 | ||||
| -rw-r--r-- | bgpd/bgp_memory.c | 1 | ||||
| -rw-r--r-- | bgpd/bgp_memory.h | 1 | ||||
| -rw-r--r-- | bgpd/bgp_route.c | 3 | ||||
| -rw-r--r-- | bgpd/bgp_route.h | 15 | 
8 files changed, 318 insertions, 28 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 83c5dc534e..2f1217945e 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1485,10 +1485,10 @@ static void update_evpn_route_entry_sync_info(struct bgp *bgp,   * or the global route table.   */  static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, -				   afi_t afi, safi_t safi, struct bgp_dest *dest, -				   struct attr *attr, int add, -				   struct bgp_path_info **pi, uint8_t flags, -				   uint32_t seq, bool setup_sync, +				   afi_t afi, safi_t safi, +				   struct bgp_dest *dest, struct attr *attr, +				   int add, struct bgp_path_info **pi, +				   uint8_t flags, uint32_t seq, bool vpn_rt,  				   bool *old_is_sync)  {  	struct bgp_path_info *tmp_pi; @@ -1520,7 +1520,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,  	/* if a local path is being added with a non-zero esi look  	 * for SYNC paths from ES peers and bubble up the sync-info  	 */ -	update_evpn_route_entry_sync_info(bgp, dest, attr, seq, setup_sync); +	update_evpn_route_entry_sync_info(bgp, dest, attr, seq, vpn_rt);  	/* For non-GW MACs, update MAC mobility seq number, if needed. */  	if (seq && !CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) @@ -1612,6 +1612,14 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,  		}  	} +	/* MAC-IP routes in the VNI route table are linked to the +	 * destination ES +	 */ +	if (route_change && vpn_rt +	    && (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)) +		bgp_evpn_path_es_link(tmp_pi, vpn->vni, +				      bgp_evpn_attr_get_esi(tmp_pi->attr)); +  	/* Return back the route entry. */  	*pi = tmp_pi;  	return route_change; @@ -2513,7 +2521,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,  	if (!pi) {  		/* Create an info */ -		(void)bgp_create_evpn_bgp_path_info(parent_pi, dest, +		pi = bgp_create_evpn_bgp_path_info(parent_pi, dest,  						    parent_pi->attr);  	} else {  		if (attrhash_cmp(pi->attr, parent_pi->attr) @@ -2539,6 +2547,11 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,  		pi->uptime = bgp_clock();  	} +	/* MAC-IP routes in the VNI table are linked to the destination ES */ +	if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) +		bgp_evpn_path_es_link(pi, vpn->vni, +				      bgp_evpn_attr_get_esi(pi->attr)); +  	/* Perform route selection and update zebra, if required. */  	ret = evpn_route_select_install(bgp, vpn, dest); @@ -2857,20 +2870,46 @@ static inline bool  bgp_evpn_skip_vrf_import_of_local_es(const struct prefix_evpn *evp,  				     struct bgp_path_info *pi, int install)  { -	if ((evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) -	    && bgp_evpn_attr_is_local_es(pi->attr)) { -		if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) { -			char esi_buf[ESI_STR_LEN]; -			char prefix_buf[PREFIX_STRLEN]; +	esi_t *esi; +	struct in_addr nh; -			zlog_debug( -				"vrf %s of evpn prefix %s skipped, local es %s", -				install ? "import" : "unimport", -				prefix2str(evp, prefix_buf, sizeof(prefix_buf)), -				esi_to_str(bgp_evpn_attr_get_esi(pi->attr), -					   esi_buf, sizeof(esi_buf))); +	if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) { +		esi = bgp_evpn_attr_get_esi(pi->attr); + +		/* Don't import routes that point to a local destination */ +		if (bgp_evpn_attr_is_local_es(pi->attr)) { +			if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) { +				char esi_buf[ESI_STR_LEN]; + +				zlog_debug( +					"vrf %s of evpn prefix %pFX skipped, local es %s", +					install ? "import" : "unimport", evp, +					esi_to_str(esi, esi_buf, +						   sizeof(esi_buf))); +			} +			return true; +		} + +		/* Don't import routes with ES as destination if the nexthop +		 * has not been advertised via the EAD-ES +		 */ +		if (pi->attr) +			nh = pi->attr->nexthop; +		else +			nh.s_addr = 0; +		if (!bgp_evpn_es_is_vtep_active(esi, nh)) { +			if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) { +				char esi_buf[ESI_STR_LEN]; + +				zlog_debug( +					"vrf %s of evpn prefix %pFX skipped, nh %pI4 inactive in es %s", +					install ? "import" : "unimport", evp, +					&nh, +					esi_to_str(esi, esi_buf, +						   sizeof(esi_buf))); +			} +			return true;  		} -		return true;  	}  	return false;  } @@ -3210,9 +3249,11 @@ static int install_uninstall_route_in_vnis(struct bgp *bgp, afi_t afi,  /*   * Install or uninstall route for appropriate VNIs/ESIs.   */ -static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, -					const struct prefix *p, -					struct bgp_path_info *pi, int import) +static int bgp_evpn_install_uninstall_table(struct bgp *bgp, afi_t afi, +					    safi_t safi, const struct prefix *p, +					    struct bgp_path_info *pi, +					    int import, bool in_vni_rt, +					    bool in_vrf_rt)  {  	struct prefix_evpn *evp = (struct prefix_evpn *)p;  	struct attr *attr = pi->attr; @@ -3274,13 +3315,13 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,  		    evp->prefix.route_type == BGP_EVPN_AD_ROUTE ||  		    evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) { -			irt = lookup_import_rt(bgp, eval); +			irt = in_vni_rt ? lookup_import_rt(bgp, eval) : NULL;  			if (irt)  				install_uninstall_route_in_vnis(  					bgp, afi, safi, evp, pi, irt->vnis,  					import); -			vrf_irt = lookup_vrf_import_rt(eval); +			vrf_irt = in_vrf_rt ? lookup_vrf_import_rt(eval) : NULL;  			if (vrf_irt)  				install_uninstall_route_in_vrfs(  					bgp, afi, safi, evp, pi, vrf_irt->vrfs, @@ -3299,8 +3340,11 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,  			    || type == ECOMMUNITY_ENCODE_IP) {  				memcpy(&eval_tmp, eval, ecom->unit_size);  				mask_ecom_global_admin(&eval_tmp, eval); -				irt = lookup_import_rt(bgp, &eval_tmp); -				vrf_irt = lookup_vrf_import_rt(&eval_tmp); +				if (in_vni_rt) +					irt = lookup_import_rt(bgp, &eval_tmp); +				if (in_vrf_rt) +					vrf_irt = +						lookup_vrf_import_rt(&eval_tmp);  			}  			if (irt) @@ -3330,6 +3374,31 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,  }  /* + * Install or uninstall route for appropriate VNIs/ESIs. + */ +static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi, +					const struct prefix *p, +					struct bgp_path_info *pi, int import) +{ +	return bgp_evpn_install_uninstall_table(bgp, afi, safi, p, pi, import, +						true, true); +} + +/* Import the pi into vrf routing tables */ +void bgp_evpn_import_route_in_vrfs(struct bgp_path_info *pi, int import) +{ +	struct bgp *bgp_evpn; + +	bgp_evpn = bgp_get_evpn(); +	if (!bgp_evpn) +		return; + +	bgp_evpn_install_uninstall_table(bgp_evpn, AFI_L2VPN, SAFI_EVPN, +					 &pi->net->p, pi, import, false /*vpn*/, +					 true /*vrf*/); +} + +/*   * delete and withdraw all ipv4 and ipv6 routes in the vrf table as type-5   * routes   */ diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 39523ea206..029c2e838e 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -66,6 +66,10 @@ static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);  static void bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi);  static uint32_t bgp_evpn_es_get_active_vtep_cnt(struct bgp_evpn_es *es);  static void bgp_evpn_l3nhg_update_on_vtep_chg(struct bgp_evpn_es *es); +static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi); +static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller); +static void bgp_evpn_es_path_all_update(struct bgp_evpn_es_vtep *es_vtep, +					bool active);  esi_t zero_esi_buf, *zero_esi = &zero_esi_buf; @@ -1231,8 +1235,19 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,  		/* send remote ES to zebra */  		bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active); -		/* update L3NHG associated with the ES */ -		bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es); +		/* If VTEP becomes active update the NHG first and then +		 * the exploded routes. If VTEP becomes inactive update +		 * routes first. This ordering is done to avoid deleting +		 * the NHG while there are dependent routes against +		 * it. +		 */ +		if (new_active) { +			bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es); +			bgp_evpn_es_path_all_update(es_vtep, true /*active*/); +		} else { +			bgp_evpn_es_path_all_update(es_vtep, false /*active*/); +			bgp_evpn_l3nhg_update_on_vtep_chg(es_vtep->es); +		}  		/* queue up the es for background consistency checks */  		bgp_evpn_es_cons_checks_pend_add(es_vtep->es); @@ -1309,6 +1324,167 @@ static void bgp_evpn_es_vtep_del(struct bgp *bgp,  		bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);  } +bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh) +{ +	struct bgp_evpn_es *es; +	struct bgp_evpn_es_vtep *es_vtep; +	struct listnode *node = NULL; +	bool rc = false; + +	if (!memcmp(esi, zero_esi, sizeof(*esi)) || !nh.s_addr) +		return true; + +	es = bgp_evpn_es_find(esi); +	if (!es) +		return false; + +	for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) { +		if (es_vtep->vtep_ip.s_addr == nh.s_addr) { +			if (CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE)) +				rc = true; +			break; +		} +	} +	return rc; +} + +/********************** ES MAC-IP paths ************************************* + * MAC-IP routes in the VNI routing table are linked to the destination + * ES for efficient updates on ES changes (such as VTEP add/del). + ****************************************************************************/ +void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info) +{ +	bgp_evpn_path_es_unlink(es_info); +	XFREE(MTYPE_BGP_EVPN_PATH_ES_INFO, es_info); +} + +static struct bgp_path_es_info * +bgp_evpn_path_es_info_new(struct bgp_path_info *pi, vni_t vni) +{ +	struct bgp_path_info_extra *e; + +	e = bgp_path_info_extra_get(pi); + +	/* If es_info doesn't exist allocate it */ +	if (!e->es_info) { +		e->es_info = XCALLOC(MTYPE_BGP_EVPN_PATH_ES_INFO, +				     sizeof(struct bgp_path_es_info)); +		e->es_info->pi = pi; +		e->es_info->vni = vni; +	} + +	return e->es_info; +} + +void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info) +{ +	struct bgp_evpn_es *es = es_info->es; +	struct bgp_path_info *pi; +	char prefix_buf[PREFIX_STRLEN]; + +	if (!es) +		return; + +	pi = es_info->pi; +	if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) +		zlog_debug( +			"path %s unlinked from es %s", +			prefix2str(&pi->net->p, prefix_buf, sizeof(prefix_buf)), +			es->esi_str); + +	list_delete_node(es->macip_path_list, &es_info->es_listnode); +	es_info->es = NULL; + +	/* if there are no other references against the ES it +	 * needs to be freed +	 */ +	bgp_evpn_es_free(es, __func__); + +	/* Note we don't free the path es_info on unlink; it will be freed up +	 * along with the path. +	 */ +} + +void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, esi_t *esi) +{ +	struct bgp_path_es_info *es_info; +	struct bgp_evpn_es *es; +	struct bgp *bgp_evpn = bgp_get_evpn(); +	char prefix_buf[PREFIX_STRLEN]; + +	es_info = pi->extra ? pi->extra->es_info : NULL; +	/* if the esi is zero just unlink the path from the old es */ +	if (!esi || !memcmp(esi, zero_esi, sizeof(*esi))) { +		if (es_info) +			bgp_evpn_path_es_unlink(es_info); +		return; +	} + +	if (!bgp_evpn) +		return; + +	/* setup es_info against the path if it doesn't aleady exist */ +	if (!es_info) +		es_info = bgp_evpn_path_es_info_new(pi, vni); + +	/* find-create ES */ +	es = bgp_evpn_es_find(esi); +	if (!es) +		bgp_evpn_es_new(bgp_evpn, esi); + +	/* dup check */ +	if (es_info->es == es) +		return; + +	/* unlink old ES if any */ +	bgp_evpn_path_es_unlink(es_info); + +	if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) +		zlog_debug( +			"path %s linked to es %s", +			prefix2str(&pi->net->p, prefix_buf, sizeof(prefix_buf)), +			es->esi_str); + +	/* link mac-ip path to the new destination ES */ +	es_info->es = es; +	listnode_init(&es_info->es_listnode, es_info); +	listnode_add_sort(es->macip_path_list, &es_info->es_listnode); +} + +static void bgp_evpn_es_path_all_update(struct bgp_evpn_es_vtep *es_vtep, +					bool active) +{ +	struct listnode *node; +	struct bgp_path_es_info *es_info; +	struct bgp_path_info *pi; +	struct bgp_path_info *parent_pi; +	struct bgp_evpn_es *es = es_vtep->es; +	char prefix_buf[PREFIX_STRLEN]; + +	if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) +		zlog_debug("update all paths linked to es %s", es->esi_str); + +	for (ALL_LIST_ELEMENTS_RO(es->macip_path_list, node, es_info)) { +		pi = es_info->pi; +		if (pi->sub_type != BGP_ROUTE_IMPORTED) +			continue; + +		parent_pi = pi->extra ? pi->extra->parent : NULL; +		if (!parent_pi || !parent_pi->attr) +			continue; + +		if (es_vtep->vtep_ip.s_addr != parent_pi->attr->nexthop.s_addr) +			continue; + +		if (BGP_DEBUG(evpn_mh, EVPN_MH_RT)) +			zlog_debug("update path %s linked to es %s", +				   prefix2str(&parent_pi->net->p, prefix_buf, +					      sizeof(prefix_buf)), +				   es->esi_str); +		bgp_evpn_import_route_in_vrfs(parent_pi, active ? 1 : 0); +	} +} +  /* compare ES-IDs for the global ES RB tree */  static int bgp_es_rb_cmp(const struct bgp_evpn_es *es1,  		const struct bgp_evpn_es *es2) @@ -1361,6 +1537,10 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)  	es->es_vrf_list = list_new();  	listset_app_node_mem(es->es_vrf_list); +	/* Initialise the route list used for efficient event handling */ +	es->macip_path_list = list_new(); +	listset_app_node_mem(es->macip_path_list); +  	QOBJ_REG(es, bgp_evpn_es);  	return es; @@ -1372,7 +1552,8 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)   */  static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)  { -	if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) +	if ((es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) +	    || listcount(es->macip_path_list))  		return;  	if (BGP_DEBUG(evpn_mh, EVPN_MH_ES)) @@ -1382,6 +1563,7 @@ static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)  	list_delete(&es->es_evi_list);  	list_delete(&es->es_vrf_list);  	list_delete(&es->es_vtep_list); +	list_delete(&es->macip_path_list);  	bgp_table_unlock(es->route_table);  	/* remove the entry from various databases */ diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index bf957e581a..be4456828e 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -99,6 +99,11 @@ struct bgp_evpn_es {  	/* List of ES-VRFs associated with this ES */  	struct list *es_vrf_list; +	/* List of MAC-IP global routes using this ES as destination - +	 * element is bgp_path_info_extra->es_info +	 */ +	struct list *macip_path_list; +  	/* Number of remote VNIs referencing this ES */  	uint32_t remote_es_evi_cnt; @@ -344,5 +349,10 @@ extern void bgp_evpn_vrf_es_init(struct bgp *bgp_vrf);  extern void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi);  extern void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi,  				struct bgp *bgp_vrf); +extern void bgp_evpn_path_es_info_free(struct bgp_path_es_info *es_info); +extern void bgp_evpn_path_es_unlink(struct bgp_path_es_info *es_info); +extern void bgp_evpn_path_es_link(struct bgp_path_info *pi, vni_t vni, +				  esi_t *esi); +extern bool bgp_evpn_es_is_vtep_active(esi_t *esi, struct in_addr nh);  #endif /* _FRR_BGP_EVPN_MH_H */ diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h index e8e68c8387..cd4920e3d0 100644 --- a/bgpd/bgp_evpn_private.h +++ b/bgpd/bgp_evpn_private.h @@ -630,4 +630,13 @@ extern struct bgp_dest *  bgp_global_evpn_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,  			    const struct prefix_evpn *evp,  			    struct prefix_rd *prd); +extern struct bgp_node *bgp_global_evpn_node_get(struct bgp_table *table, +						 afi_t afi, safi_t safi, +						 const struct prefix_evpn *evp, +						 struct prefix_rd *prd); +extern struct bgp_node * +bgp_global_evpn_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi, +			    const struct prefix_evpn *evp, +			    struct prefix_rd *prd); +extern void bgp_evpn_import_route_in_vrfs(struct bgp_path_info *pi, int import);  #endif /* _BGP_EVPN_PRIVATE_H */ diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index 1582b90a2e..f9aac35d05 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -118,6 +118,7 @@ DEFINE_MTYPE(BGPD, LCOMMUNITY_VAL, "Large Community value")  DEFINE_MTYPE(BGPD, BGP_EVPN, "BGP EVPN Information")  DEFINE_MTYPE(BGPD, BGP_EVPN_MH_INFO, "BGP EVPN MH Information")  DEFINE_MTYPE(BGPD, BGP_EVPN_ES_VTEP, "BGP EVPN ES VTEP") +DEFINE_MTYPE(BGPD, BGP_EVPN_PATH_ES_INFO, "BGP EVPN PATH ES Information")  DEFINE_MTYPE(BGPD, BGP_EVPN_ES_EVI_VTEP, "BGP EVPN ES-EVI VTEP")  DEFINE_MTYPE(BGPD, BGP_EVPN_ES, "BGP EVPN ESI Information")  DEFINE_MTYPE(BGPD, BGP_EVPN_ES_EVI, "BGP EVPN ES-per-EVI Information") diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index 058fa4b295..a95d9ef931 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -116,6 +116,7 @@ DECLARE_MTYPE(BGP_EVPN_ES)  DECLARE_MTYPE(BGP_EVPN_ES_EVI)  DECLARE_MTYPE(BGP_EVPN_ES_VRF)  DECLARE_MTYPE(BGP_EVPN_ES_VTEP) +DECLARE_MTYPE(BGP_EVPN_PATH_ES_INFO)  DECLARE_MTYPE(BGP_EVPN_ES_EVI_VTEP)  DECLARE_MTYPE(BGP_EVPN) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index df30897dc6..29dbdbad89 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -244,6 +244,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)  	if (e->aggr_suppressors)  		list_delete(&e->aggr_suppressors); +	if (e->es_info) +		bgp_evpn_path_es_info_free(e->es_info); +  	if ((*extra)->bgp_fs_iprule)  		list_delete(&((*extra)->bgp_fs_iprule));  	if ((*extra)->bgp_fs_pbr) diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 0b76d7504b..17ca3f8b38 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -102,6 +102,19 @@ enum bgp_show_adj_route_type {  #define BGP_NLRI_PARSE_ERROR_EVPN_TYPE1_SIZE -15  #define BGP_NLRI_PARSE_ERROR -32 +/* MAC-IP/type-2 path_info in the global routing table is linked to the + * destination ES + */ +struct bgp_path_es_info { +	/* back pointer to the route */ +	struct bgp_path_info *pi; +	vni_t vni; +	/* destination ES */ +	struct bgp_evpn_es *es; +	/* memory used for linking the path to the destination ES */ +	struct listnode es_listnode; +}; +  /* Ancillary information to struct bgp_path_info,   * used for uncommonly used data (aggregation, MPLS, etc.)   * and lazily allocated to save memory. @@ -188,6 +201,8 @@ struct bgp_path_info_extra {  	struct list *bgp_fs_pbr;  	/* presence of FS pbr iprule based entry */  	struct list *bgp_fs_iprule; +	/* Destination Ethernet Segment links for EVPN MH */ +	struct bgp_path_es_info *es_info;  };  struct bgp_path_info {  | 
