mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-02 20:27:14 +00:00
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>
This commit is contained in:
parent
c589d84746
commit
26c03e43fb
119
bgpd/bgp_evpn.c
119
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)
|
||||
@ -3329,6 +3373,31 @@ static int install_uninstall_evpn_route(struct bgp *bgp, afi_t afi, safi_t safi,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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")
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user