summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_evpn.c284
-rw-r--r--bgpd/bgp_evpn_mh.c14
-rw-r--r--bgpd/bgp_evpn_private.h55
-rw-r--r--bgpd/bgp_evpn_vty.c117
-rw-r--r--bgpd/bgp_route.c39
-rw-r--r--bgpd/bgp_route.h9
6 files changed, 375 insertions, 143 deletions
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 58f5e9a226..4e5a62ce45 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -552,10 +552,14 @@ static void evpn_convert_nexthop_to_ipv6(struct attr *attr)
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
}
-struct bgp_dest *bgp_global_evpn_node_get(struct bgp_table *table, afi_t afi,
+/*
+ * Wrapper for node get in global table.
+ */
+struct bgp_dest *bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi,
safi_t safi,
const struct prefix_evpn *evp,
- struct prefix_rd *prd)
+ struct prefix_rd *prd,
+ const struct bgp_path_info *local_pi)
{
struct prefix_evpn global_p;
@@ -565,14 +569,28 @@ struct bgp_dest *bgp_global_evpn_node_get(struct bgp_table *table, afi_t afi,
*/
evpn_type1_prefix_global_copy(&global_p, evp);
evp = &global_p;
+ } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ local_pi) {
+ /*
+ * prefix in the global table needs MAC, ensure it's present,
+ * using one from local table's path_info.
+ */
+ evpn_type2_prefix_global_copy(
+ &global_p, evp,
+ *evpn_type2_path_info_get_mac(local_pi));
+ evp = &global_p;
}
return bgp_afi_node_get(table, afi, safi, (struct prefix *)evp, prd);
}
-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)
+/*
+ * Wrapper for node lookup in global table.
+ */
+struct bgp_dest *
+bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
+ const struct prefix_evpn *evp,
+ struct prefix_rd *prd,
+ const struct bgp_path_info *local_pi)
{
struct prefix_evpn global_p;
@@ -582,15 +600,86 @@ struct bgp_dest *bgp_global_evpn_node_lookup(struct bgp_table *table, afi_t afi,
*/
evpn_type1_prefix_global_copy(&global_p, evp);
evp = &global_p;
+ } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ local_pi) {
+ /*
+ * prefix in the global table needs MAC, ensure it's present,
+ * using one from local table's path_info.
+ */
+ evpn_type2_prefix_global_copy(
+ &global_p, evp,
+ *evpn_type2_path_info_get_mac(local_pi));
+ evp = &global_p;
}
return bgp_afi_node_lookup(table, afi, safi, (struct prefix *)evp, prd);
}
/*
+ * Wrapper for node get in VNI table.
+ */
+struct bgp_dest *bgp_evpn_vni_node_get(struct bgp_table *const table,
+ const struct prefix_evpn *evp,
+ const struct bgp_path_info *parent_pi)
+{
+ struct prefix_evpn vni_p;
+
+ if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE && parent_pi) {
+ /* prefix in the global table doesn't include the VTEP-IP so
+ * we need to create a different copy for the VNI
+ */
+ evpn_type1_prefix_vni_copy(&vni_p, evp,
+ parent_pi->attr->nexthop);
+ evp = &vni_p;
+ } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ !is_evpn_prefix_ipaddr_none(evp)) {
+ /*
+ * IP prefix in the vni table doesn't include MAC so
+ * we need to create a different copy of the prefix.
+ *
+ * However, if it's MAC-only, keep it.
+ */
+ evpn_type2_prefix_vni_copy(&vni_p, evp);
+ evp = &vni_p;
+ }
+ return bgp_node_get(table, (struct prefix *)evp);
+}
+
+/*
+ * Wrapper for node lookup in VNI table.
+ */
+struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgp_table *const table,
+ const struct prefix_evpn *evp,
+ const struct bgp_path_info *parent_pi)
+{
+ struct prefix_evpn vni_p;
+
+ if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE && parent_pi) {
+ /* prefix in the global table doesn't include the VTEP-IP so
+ * we need to create a different copy for the VNI
+ */
+ evpn_type1_prefix_vni_copy(&vni_p, evp,
+ parent_pi->attr->nexthop);
+ evp = &vni_p;
+ } else if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ !is_evpn_prefix_ipaddr_none(evp)) {
+ /*
+ * IP prefix in the vni table doesn't include MAC so
+ * we need to create a different copy of the prefix.
+ *
+ * However, if it's MAC-only, keep it.
+ */
+ evpn_type2_prefix_vni_copy(&vni_p, evp);
+ evp = &vni_p;
+ }
+ return bgp_node_lookup(table, (struct prefix *)evp);
+}
+
+/*
* Add (update) or delete MACIP from zebra.
*/
static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
const struct prefix_evpn *p,
+ const struct ethaddr *mac,
struct in_addr remote_vtep_ip, int add,
uint8_t flags, uint32_t seq, esi_t *esi)
{
@@ -620,7 +709,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
s, add ? ZEBRA_REMOTE_MACIP_ADD : ZEBRA_REMOTE_MACIP_DEL,
bgp->vrf_id);
stream_putl(s, vpn->vni);
- stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */
+
+ if (mac) /* Mac Addr */
+ stream_put(s, &mac->octet, ETH_ALEN);
+ else
+ stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN);
+
/* IP address length and IP address, if any. */
if (is_evpn_prefix_ipaddr_none(p))
stream_putw(s, 0);
@@ -985,8 +1079,9 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
}
ret = bgp_zebra_send_remote_macip(
- bgp, vpn, p, pi->attr->nexthop, 1, flags,
- seq, bgp_evpn_attr_get_esi(pi->attr));
+ bgp, vpn, p, evpn_type2_path_info_get_mac(pi),
+ pi->attr->nexthop, 1, flags, seq,
+ bgp_evpn_attr_get_esi(pi->attr));
} else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE) {
ret = bgp_evpn_remote_es_evi_add(bgp, vpn, p);
} else {
@@ -1012,13 +1107,15 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
/* Uninstall EVPN route from zebra. */
static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
const struct prefix_evpn *p,
- struct in_addr remote_vtep_ip)
+ struct bgp_path_info *pi, bool is_sync)
{
int ret;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
- ret = bgp_zebra_send_remote_macip(bgp, vpn, p, remote_vtep_ip,
- 0, 0, 0, NULL);
+ ret = bgp_zebra_send_remote_macip(
+ bgp, vpn, p, evpn_type2_path_info_get_mac(pi),
+ (is_sync ? zero_vtep_ip : pi->attr->nexthop), 0, 0, 0,
+ NULL);
else if (p->prefix.route_type == BGP_EVPN_AD_ROUTE)
ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p);
else
@@ -1061,9 +1158,10 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table is a 2-level tree (RD-level + Prefix-level) similar to
* L3VPN routes.
*/
- global_dest = bgp_global_evpn_node_lookup(bgp->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
- &vpn->prd);
+ global_dest = bgp_evpn_global_node_lookup(
+ bgp->rib[afi][safi], afi, safi,
+ (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
+ &vpn->prd, old_local);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
@@ -1176,7 +1274,7 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
bgp, vpn,
(const struct prefix_evpn *)bgp_dest_get_prefix(
dest),
- old_select->attr->nexthop);
+ old_select, false);
}
/* Clear any route change flags. */
@@ -1362,9 +1460,8 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
build_evpn_type5_route_extcomm(bgp_vrf, &attr);
/* get the route node in global table */
- dest = bgp_global_evpn_node_get(bgp_evpn->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)evp,
- &bgp_vrf->vrf_prd);
+ dest = bgp_evpn_global_node_get(bgp_evpn->rib[afi][safi], afi, safi,
+ evp, &bgp_vrf->vrf_prd, NULL);
assert(dest);
/* create or update the route entry within the route node */
@@ -1515,9 +1612,9 @@ static void update_evpn_route_entry_sync_info(struct bgp *bgp,
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 vpn_rt,
- bool *old_is_sync)
+ const struct ethaddr *mac, 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;
struct bgp_path_info *local_pi;
@@ -1589,6 +1686,11 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
memcpy(&tmp_pi->extra->label, label, sizeof(label));
tmp_pi->extra->num_labels = num_labels;
+
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE && mac)
+ evpn_type2_path_info_set_mac(tmp_pi, *mac);
+
+
/* Mark route as self type-2 route */
if (flags && CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP))
tmp_pi->extra->af_flags = BGP_EVPN_MACIP_TYPE_SVI_IP;
@@ -1618,6 +1720,10 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
memcpy(&tmp_pi->extra->label, label, sizeof(label));
tmp_pi->extra->num_labels = num_labels;
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE &&
+ mac)
+ evpn_type2_path_info_set_mac(tmp_pi, *mac);
+
/* The attribute has changed. */
/* Add (or update) attribute to hash. */
attr_new = bgp_attr_intern(attr);
@@ -1798,12 +1904,12 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
/* First, create (or fetch) route node within the VNI. */
/* NOTE: There is no RD here. */
- dest = bgp_node_get(vpn->route_table, (struct prefix *)p);
+ dest = bgp_evpn_vni_node_get(vpn->route_table, p, NULL);
/* Create or update route entry. */
- route_change = update_evpn_route_entry(bgp, vpn, afi, safi, dest, &attr,
- 1, &pi, flags, seq,
- true /* setup_sync */, &old_is_sync);
+ route_change = update_evpn_route_entry(
+ bgp, vpn, afi, safi, dest, &attr, &p->prefix.macip_addr.mac, 1,
+ &pi, flags, seq, true /* setup_sync */, &old_is_sync);
assert(pi);
attr_new = pi->attr;
@@ -1841,7 +1947,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn, p, zero_vtep_ip);
+ evpn_zebra_uninstall(bgp, vpn, p, pi, true);
}
}
bgp_path_info_unlock(pi);
@@ -1856,12 +1962,12 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
if (route_change) {
struct bgp_path_info *global_pi;
- dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)p,
- &vpn->prd);
- update_evpn_route_entry(bgp, vpn, afi, safi, dest, attr_new, 1,
- &global_pi, flags, seq,
- false /* setup_sync */, NULL /* old_is_sync */);
+ dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
+ p, &vpn->prd, NULL);
+ update_evpn_route_entry(bgp, vpn, afi, safi, dest, attr_new,
+ NULL /* mac */, 1, &global_pi, flags,
+ seq, false /* setup_sync */,
+ NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
bgp_process(bgp, dest, afi, safi);
@@ -1915,8 +2021,8 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
return 0;
/* locate the global route entry for this type-5 prefix */
- dest = bgp_global_evpn_node_lookup(bgp_evpn->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)evp, &bgp_vrf->vrf_prd);
+ dest = bgp_evpn_global_node_lookup(bgp_evpn->rib[afi][safi], afi, safi,
+ evp, &bgp_vrf->vrf_prd, NULL);
if (!dest)
return 0;
@@ -1944,7 +2050,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* is nothing further to do.
*/
/* NOTE: There is no RD here. */
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, p, NULL);
if (!dest)
return 0;
@@ -1952,8 +2058,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table is a 2-level tree (RD-level + Prefix-level) similar to
* L3VPN routes.
*/
- global_dest = bgp_global_evpn_node_lookup(bgp->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)p, &vpn->prd);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
+ safi, p, &vpn->prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
@@ -1992,8 +2098,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
int add_l3_ecomm = 0;
struct bgp_dest *global_dest;
struct bgp_path_info *global_pi;
- struct prefix_evpn *evp =
- (struct prefix_evpn *)bgp_dest_get_prefix(dest);
+ struct prefix_evpn evp;
int route_change;
bool old_is_sync = false;
@@ -2001,6 +2106,13 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
return;
/*
+ * VNI table MAC-IP prefixes don't have MAC so make sure it's set from
+ * path info here.
+ */
+ evpn_type2_prefix_global_copy(&evp, (struct prefix_evpn *)&dest->p,
+ *evpn_type2_path_info_get_mac(local_pi));
+
+ /*
* Build attribute per local route as the MAC mobility and
* some other values could differ for different routes. The
* attributes will be shared in the hash table.
@@ -2014,18 +2126,17 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
attr.es_flags = local_pi->attr->es_flags;
if (local_pi->attr->default_gw) {
attr.default_gw = 1;
- if (is_evpn_prefix_ipaddr_v6(evp))
+ if (is_evpn_prefix_ipaddr_v6(&evp))
attr.router_flag = 1;
}
memcpy(&attr.esi, &local_pi->attr->esi, sizeof(esi_t));
- bgp_evpn_get_rmac_nexthop(vpn, evp, &attr,
- local_pi->extra->af_flags);
+ bgp_evpn_get_rmac_nexthop(vpn, &evp, &attr, local_pi->extra->af_flags);
vni2label(vpn->vni, &(attr.label));
/* Add L3 VNI RTs and RMAC for non IPv6 link-local if
* using L3 VNI for type-2 routes also.
*/
add_l3_ecomm = bgp_evpn_route_add_l3_ecomm_ok(
- vpn, evp,
+ vpn, &evp,
(attr.es_flags & ATTR_ES_IS_LOCAL) ? &attr.esi : NULL);
/* Set up extended community. */
@@ -2039,15 +2150,15 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
"VRF %s vni %u evp %pFX RMAC %pEA nexthop %pI4 esi %s esf 0x%x from %s",
vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
: " ",
- vpn->vni, evp, &attr.rmac, &attr.mp_nexthop_global_in,
+ vpn->vni, &evp, &attr.rmac, &attr.mp_nexthop_global_in,
esi_to_str(&attr.esi, buf3, sizeof(buf3)),
attr.es_flags, caller);
}
/* Update the route entry. */
route_change = update_evpn_route_entry(
- bgp, vpn, afi, safi, dest, &attr, 0, &pi, 0, seq,
- true /* setup_sync */, &old_is_sync);
+ bgp, vpn, afi, safi, dest, &attr, NULL /* mac */, 0, &pi, 0,
+ seq, true /* setup_sync */, &old_is_sync);
assert(pi);
attr_new = pi->attr;
@@ -2082,8 +2193,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn,
- evp, zero_vtep_ip);
+ evpn_zebra_uninstall(bgp, vpn, &evp, pi, true);
}
}
@@ -2093,13 +2203,14 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
if (route_change) {
/* Update route in global routing table. */
- global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi,
- safi, evp, &vpn->prd);
+ global_dest = bgp_evpn_global_node_get(
+ bgp->rib[afi][safi], afi, safi, &evp, &vpn->prd, NULL);
assert(global_dest);
- update_evpn_route_entry(
- bgp, vpn, afi, safi, global_dest, attr_new, 0,
- &global_pi, 0, mac_mobility_seqnum(attr_new),
- false /* setup_sync */, NULL /* old_is_sync */);
+ update_evpn_route_entry(bgp, vpn, afi, safi, global_dest,
+ attr_new, NULL /* mac */, 0, &global_pi,
+ 0, mac_mobility_seqnum(attr_new),
+ false /* setup_sync */,
+ NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_dest, afi, safi);
@@ -2400,6 +2511,7 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
pi->extra->num_labels = parent_pi->extra->num_labels;
pi->extra->igpmetric = parent_pi->extra->igpmetric;
}
+
bgp_path_info_add(dest, pi);
return pi;
@@ -2589,20 +2701,12 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_path_info *local_pi;
struct attr *attr_new;
int ret;
- struct prefix_evpn ad_evp;
bool old_local_es = false;
bool new_local_es;
- /* EAD prefix in the global table doesn't include the VTEP-IP so
- * we need to create a different copy for the VNI
- */
- if (p->prefix.route_type == BGP_EVPN_AD_ROUTE)
- p = evpn_type1_prefix_vni_copy(&ad_evp, p,
- parent_pi->attr->nexthop);
-
/* Create (or fetch) route within the VNI. */
/* NOTE: There is no RD here. */
- dest = bgp_node_get(vpn->route_table, (struct prefix *)p);
+ dest = bgp_evpn_vni_node_get(vpn->route_table, p, parent_pi);
/* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@@ -2614,6 +2718,11 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Create an info */
pi = bgp_create_evpn_bgp_path_info(parent_pi, dest,
parent_pi->attr);
+
+ if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
+ evpn_type2_path_info_set_mac(pi,
+ p->prefix.macip_addr.mac);
+
new_local_es = bgp_evpn_attr_is_local_es(pi->attr);
} else {
if (attrhash_cmp(pi->attr, parent_pi->attr)
@@ -2765,18 +2874,10 @@ static int uninstall_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_path_info *pi;
struct bgp_path_info *local_pi;
int ret;
- struct prefix_evpn ad_evp;
-
- /* EAD prefix in the global table doesn't include the VTEP-IP so
- * we need to create a different copy for the VNI
- */
- if (p->prefix.route_type == BGP_EVPN_AD_ROUTE)
- p = evpn_type1_prefix_vni_copy(&ad_evp, p,
- parent_pi->attr->nexthop);
/* Locate route within the VNI. */
/* NOTE: There is no RD here. */
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, p, parent_pi);
if (!dest)
return 0;
@@ -3623,7 +3724,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (bgp_evpn_vni_flood_mode_get(bgp, vpn)
== VXLAN_FLOOD_HEAD_END_REPL) {
build_evpn_type3_prefix(&p, vpn->originator_ip);
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, &p, NULL);
if (!dest) /* unexpected */
return 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
@@ -3637,11 +3738,12 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
}
attr = pi->attr;
- global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi],
- afi, safi, &p, &vpn->prd);
- update_evpn_route_entry(bgp, vpn, afi, safi, global_dest, attr,
- 1, &pi, 0, mac_mobility_seqnum(attr),
- false /* setup_sync */, NULL /* old_is_sync */);
+ global_dest = bgp_evpn_global_node_get(
+ bgp->rib[afi][safi], afi, safi, &p, &vpn->prd, NULL);
+ update_evpn_route_entry(
+ bgp, vpn, afi, safi, global_dest, attr, NULL /* mac */,
+ 1, &pi, 0, mac_mobility_seqnum(attr),
+ false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
bgp_process(bgp, global_dest, afi, safi);
@@ -3653,6 +3755,7 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
*/
for (dest = bgp_table_top(vpn->route_table); dest;
dest = bgp_route_next(dest)) {
+ struct prefix_evpn tmp_evp;
const struct prefix_evpn *evp =
(const struct prefix_evpn *)bgp_dest_get_prefix(dest);
@@ -3672,19 +3775,28 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
if (!pi)
continue;
+ /*
+ * VNI table MAC-IP prefixes don't have MAC so make sure it's
+ * set from path info here.
+ */
+ evpn_type2_prefix_global_copy(
+ &tmp_evp, evp, *evpn_type2_path_info_get_mac(pi));
+
/* Create route in global routing table using this route entry's
* attribute.
*/
attr = pi->attr;
- global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
- evp, &vpn->prd);
+ global_dest =
+ bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
+ &tmp_evp, &vpn->prd, NULL);
assert(global_dest);
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),
+ bgp, vpn, afi, safi, global_dest, attr,
+ NULL /* mac */, 1, &global_pi, 0,
+ mac_mobility_seqnum(attr),
false /* setup_sync */, NULL /* old_is_sync */);
} else {
/* Type-1 route */
@@ -3724,8 +3836,8 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
/* Remove type-3 route for this VNI from global table. */
build_evpn_type3_prefix(&p, vpn->originator_ip);
- global_dest = bgp_global_evpn_node_lookup(bgp->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)&p, &vpn->prd);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
+ safi, &p, &vpn->prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
delete_evpn_route_entry(bgp, afi, safi, global_dest, &pi);
@@ -5482,7 +5594,7 @@ int bgp_evpn_local_macip_del(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
delete_evpn_route(bgp, vpn, &p);
} else {
/* Re-instate the current remote best path if any */
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, &p, NULL);
if (dest) {
evpn_zebra_reinstall_best_route(bgp, vpn, dest);
bgp_dest_unlock_node(dest);
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 1d40664aeb..a0ab0881e7 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -498,9 +498,8 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
/* Next, locate route node in the global EVPN routing table.
* Note that this table is a 2-level tree (RD-level + Prefix-level)
*/
- global_dest =
- bgp_global_evpn_node_lookup(bgp->rib[afi][safi], afi, safi,
- (const struct prefix_evpn *)p, prd);
+ global_dest = bgp_evpn_global_node_lookup(bgp->rib[afi][safi], afi,
+ safi, p, prd, NULL);
if (global_dest) {
/* Delete route entry in the global EVPN table. */
@@ -675,8 +674,9 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
if (route_changed) {
struct bgp_path_info *global_pi;
- dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
- p, &es->es_base_frag->prd);
+ dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
+ p, &es->es_base_frag->prd,
+ NULL);
bgp_evpn_mh_route_update(bgp, es, NULL, afi, safi, dest,
attr_new, &global_pi, &route_changed);
@@ -1015,8 +1015,8 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
if (route_changed) {
struct bgp_path_info *global_pi;
- dest = bgp_global_evpn_node_get(bgp->rib[afi][safi], afi, safi,
- p, global_rd);
+ dest = bgp_evpn_global_node_get(bgp->rib[afi][safi], afi, safi,
+ p, global_rd, NULL);
bgp_evpn_mh_route_update(bgp, es, vpn, afi, safi, dest,
attr_new, &global_pi, &route_changed);
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 64fdc29704..9b4405afe7 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -543,6 +543,39 @@ static inline struct prefix_evpn *evpn_type1_prefix_vni_copy(
return vni_p;
}
+static inline void
+evpn_type2_prefix_global_copy(struct prefix_evpn *global_p,
+ const struct prefix_evpn *vni_p,
+ const struct ethaddr mac)
+{
+ memcpy(global_p, vni_p, sizeof(*global_p));
+ global_p->prefix.macip_addr.mac = mac;
+}
+
+static inline void
+evpn_type2_prefix_vni_copy(struct prefix_evpn *vni_p,
+ const struct prefix_evpn *global_p)
+{
+ memcpy(vni_p, global_p, sizeof(*vni_p));
+ memset(&vni_p->prefix.macip_addr.mac, 0, sizeof(struct ethaddr));
+}
+
+/* Get MAC of path_info prefix */
+static inline struct ethaddr *
+evpn_type2_path_info_get_mac(const struct bgp_path_info *local_pi)
+{
+ assert(local_pi->extra);
+ return &local_pi->extra->mac;
+}
+
+/* Set MAC of path_info prefix */
+static inline void evpn_type2_path_info_set_mac(struct bgp_path_info *local_pi,
+ const struct ethaddr mac)
+{
+ assert(local_pi->extra);
+ local_pi->extra->mac = mac;
+}
+
static inline int evpn_default_originate_set(struct bgp *bgp, afi_t afi,
safi_t safi)
{
@@ -633,14 +666,24 @@ extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
int vni_list_cmp(void *p1, void *p2);
extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_dest *dest);
-extern struct bgp_dest *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_dest *
-bgp_global_evpn_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
+bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi,
+ const struct prefix_evpn *evp, struct prefix_rd *prd,
+ const struct bgp_path_info *local_pi);
+extern struct bgp_dest *
+bgp_evpn_global_node_lookup(struct bgp_table *table, afi_t afi, safi_t safi,
const struct prefix_evpn *evp,
- struct prefix_rd *prd);
+ struct prefix_rd *prd,
+ const struct bgp_path_info *local_pi);
+extern struct bgp_dest *
+bgp_evpn_vni_node_get(struct bgp_table *const table,
+ const struct prefix_evpn *evp,
+ const struct bgp_path_info *parent_pi);
+extern struct bgp_dest *
+bgp_evpn_vni_node_lookup(const struct bgp_table *const table,
+ const struct prefix_evpn *evp,
+ const struct bgp_path_info *parent_pi);
+extern void bgp_evpn_import_route_in_vrfs(struct bgp_path_info *pi, int import);
extern void bgp_evpn_update_type2_route_entry(struct bgp *bgp,
struct bgpevpn *vpn,
struct bgp_node *rn,
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 5ad5cf8bff..fc2271ed72 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -735,7 +735,8 @@ static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,
if (detail)
route_vty_out_detail(
- vty, bgp, rn, pi, AFI_L2VPN, SAFI_EVPN,
+ vty, bgp, rn, bgp_dest_get_prefix(rn),
+ pi, AFI_L2VPN, SAFI_EVPN,
RPKI_NOT_BEING_USED, json_path);
else
route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
@@ -818,6 +819,7 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
* with code that already exists).
*/
for (; pi; pi = pi->next) {
+ struct prefix tmp_p;
json_object *json_path = NULL;
if (vtep_ip.s_addr != INADDR_ANY
@@ -825,16 +827,30 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
&(pi->attr->nexthop)))
continue;
+ if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
+ /*
+ * VNI table MAC-IP prefixes don't have MAC so
+ * make sure it's set from path info
+ * here.
+ */
+ evpn_type2_prefix_global_copy(
+ (struct prefix_evpn *)&tmp_p,
+ (struct prefix_evpn *)p,
+ *evpn_type2_path_info_get_mac(pi));
+ } else
+ memcpy(&tmp_p, p, sizeof(tmp_p));
+
+
if (json)
json_path = json_object_new_array();
if (detail)
- route_vty_out_detail(vty, bgp, dest, pi,
+ route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,
AFI_L2VPN, SAFI_EVPN,
RPKI_NOT_BEING_USED,
json_path);
else
- route_vty_out(vty, p, pi, 0, SAFI_EVPN,
+ route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,
json_path, false);
if (json)
@@ -846,6 +862,19 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
if (json) {
if (add_prefix_to_json) {
+ struct prefix tmp_p;
+
+ if (evp->prefix.route_type ==
+ BGP_EVPN_MAC_IP_ROUTE) {
+ pi = bgp_dest_get_bgp_path_info(dest);
+ evpn_type2_prefix_global_copy(
+ (struct prefix_evpn *)&tmp_p,
+ (struct prefix_evpn *)p,
+ *evpn_type2_path_info_get_mac(
+ pi));
+ } else
+ memcpy(&tmp_p, p, sizeof(tmp_p));
+
json_object_string_addf(json_prefix, "prefix",
"%pFX", p);
json_object_int_add(json_prefix, "prefixLen",
@@ -2371,7 +2400,7 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
/* See if route exists. */
build_evpn_type3_prefix(&p, orig_ip);
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, &p, NULL);
if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
if (!json)
vty_out(vty, "%% Network not in table\n");
@@ -2386,7 +2415,8 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
json_paths = json_object_new_array();
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json);
+ route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
+ NULL, afi, safi, json);
/* Display each path for this prefix. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
@@ -2395,8 +2425,9 @@ static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
if (json)
json_path = json_object_new_array();
- route_vty_out_detail(vty, bgp, dest, pi, afi, safi,
- RPKI_NOT_BEING_USED, json_path);
+ route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
+ pi, afi, safi, RPKI_NOT_BEING_USED,
+ json_path);
if (json)
json_object_array_add(json_paths, json_path);
@@ -2427,6 +2458,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
{
struct bgpevpn *vpn;
struct prefix_evpn p;
+ struct prefix_evpn tmp_p;
struct bgp_dest *dest;
struct bgp_path_info *pi;
uint32_t path_cnt = 0;
@@ -2447,7 +2479,7 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
/* See if route exists. Look for both non-sticky and sticky. */
build_evpn_type2_prefix(&p, mac, ip);
- dest = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
+ dest = bgp_evpn_vni_node_lookup(vpn->route_table, &p, NULL);
if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
if (!json)
vty_out(vty, "%% Network not in table\n");
@@ -2458,21 +2490,54 @@ static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
return;
}
+ /*
+ * MAC is per-path, we have to walk the path_info's and look for it
+ * first here.
+ */
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
+ sizeof(*mac)) == 0)
+ break;
+ }
+
+ if (!pi) {
+ if (!json)
+ vty_out(vty, "%% Network not in table\n");
+ return;
+ }
+
if (json)
json_paths = json_object_new_array();
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(vty, bgp, dest, NULL, afi, safi, json);
+ route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
+ afi, safi, json);
/* Display each path for this prefix. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
json_object *json_path = NULL;
+ /* skip non-matching MACs */
+ if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
+ sizeof(*mac)) != 0)
+ continue;
+
if (json)
json_path = json_object_new_array();
- route_vty_out_detail(vty, bgp, dest, pi, afi, safi,
- RPKI_NOT_BEING_USED, json_path);
+ /*
+ * VNI table MAC-IP prefixes don't have MAC so
+ * make sure it's set from path info
+ * here.
+ */
+ evpn_type2_prefix_global_copy(
+ (struct prefix_evpn *)&tmp_p,
+ (struct prefix_evpn *)bgp_dest_get_prefix(dest),
+ *evpn_type2_path_info_get_mac(pi));
+
+ route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p,
+ pi, afi, safi, RPKI_NOT_BEING_USED,
+ json_path);
if (json)
json_object_array_add(json_paths, json_path);
@@ -2568,7 +2633,8 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
}
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(vty, bgp, dest, prd, afi, safi, json);
+ route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
+ prd, afi, safi, json);
if (json)
json_paths = json_object_new_array();
@@ -2580,8 +2646,9 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
if (json)
json_path = json_object_new_array();
- route_vty_out_detail(vty, bgp, dest, pi, afi, safi,
- RPKI_NOT_BEING_USED, json_path);
+ route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
+ pi, afi, safi, RPKI_NOT_BEING_USED,
+ json_path);
if (json)
json_object_array_add(json_paths, json_path);
@@ -2673,8 +2740,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
}
/* Prefix and num paths displayed once per prefix. */
- route_vty_out_detail_header(vty, bgp, dest, prd, afi,
- safi, json_prefix);
+ route_vty_out_detail_header(
+ vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
+ afi, safi, json_prefix);
prefix_cnt++;
}
@@ -2689,8 +2757,9 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
if (json)
json_path = json_object_new_array();
- route_vty_out_detail(vty, bgp, dest, pi, afi, safi,
- RPKI_NOT_BEING_USED, json_path);
+ route_vty_out_detail(
+ vty, bgp, dest, bgp_dest_get_prefix(dest), pi,
+ afi, safi, RPKI_NOT_BEING_USED, json_path);
if (json)
json_object_array_add(json_paths, json_path);
@@ -2807,7 +2876,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
} else
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(
- vty, bgp, dest, (struct prefix_rd *)rd_destp,
+ vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
AFI_L2VPN, SAFI_EVPN, json_prefix);
/* For EVPN, the prefix is displayed for each path (to
@@ -2822,7 +2891,7 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
if (json)
json_path = json_object_new_array();
- route_vty_out_detail(vty, bgp, dest, pi, AFI_L2VPN,
+ route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,
SAFI_EVPN, RPKI_NOT_BEING_USED,
json_path);
@@ -2960,6 +3029,7 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
if (detail)
route_vty_out_detail_header(
vty, bgp, dest,
+ bgp_dest_get_prefix(dest),
(struct prefix_rd *)rd_destp, AFI_L2VPN,
SAFI_EVPN, json_prefix);
@@ -2979,9 +3049,10 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
if (detail) {
route_vty_out_detail(
- vty, bgp, dest, pi, AFI_L2VPN,
- SAFI_EVPN, RPKI_NOT_BEING_USED,
- json_path);
+ vty, bgp, dest,
+ bgp_dest_get_prefix(dest), pi,
+ AFI_L2VPN, SAFI_EVPN,
+ RPKI_NOT_BEING_USED, json_path);
} else
route_vty_out(vty, p, pi, 0, SAFI_EVPN,
json_path, false);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 7d4110029e..7ec2484572 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -10003,7 +10003,8 @@ static void route_vty_out_detail_es_info(struct vty *vty,
}
void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
- struct bgp_path_info *path, afi_t afi, safi_t safi,
+ const struct prefix *p, struct bgp_path_info *path,
+ afi_t afi, safi_t safi,
enum rpki_states rpki_curr_state,
json_object *json_paths)
{
@@ -10048,7 +10049,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
if (safi == SAFI_EVPN) {
if (!json_paths)
- vty_out(vty, " Route %pRN", bn);
+ vty_out(vty, " Route %pFX", p);
}
if (path->extra) {
@@ -10209,10 +10210,9 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Line2 display Next-hop, Neighbor, Router-id */
/* Display the nexthop */
- const struct prefix *bn_p = bgp_dest_get_prefix(bn);
- if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
- bn_p->family == AF_EVPN) &&
+ if ((p->family == AF_INET || p->family == AF_ETHERNET ||
+ p->family == AF_EVPN) &&
(safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
@@ -10325,7 +10325,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* This path was originated locally */
if (path->peer == bgp->peer_self) {
- if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
+ if (safi == SAFI_EVPN || (p->family == AF_INET &&
!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (json_paths)
json_object_string_add(json_peer, "peerId",
@@ -11340,8 +11340,9 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
prd = bgp_rd_from_dest(dest, safi);
route_vty_out_detail_header(
- vty, bgp, dest, prd, table->afi,
- safi, jtemp);
+ vty, bgp, dest,
+ bgp_dest_get_prefix(dest), prd,
+ table->afi, safi, jtemp);
json_object_array_add(json_paths, jtemp);
@@ -11367,7 +11368,8 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
else {
if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
route_vty_out_detail(
- vty, bgp, dest, pi,
+ vty, bgp, dest,
+ bgp_dest_get_prefix(dest), pi,
family2afi(dest_p->family),
safi, RPKI_NOT_BEING_USED,
json_paths);
@@ -11588,12 +11590,11 @@ static void bgp_show_all_instances_routes_vty(struct vty *vty, afi_t afi,
/* Header of detailed BGP route information */
void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
- struct bgp_dest *dest,
- const struct prefix_rd *prd,
- afi_t afi, safi_t safi, json_object *json)
+ struct bgp_dest *dest, const struct prefix *p,
+ const struct prefix_rd *prd, afi_t afi,
+ safi_t safi, json_object *json)
{
struct bgp_path_info *pi;
- const struct prefix *p;
struct peer *peer;
struct listnode *node, *nnode;
char buf1[RD_ADDRSTRLEN];
@@ -11623,7 +11624,6 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
mpls_lse_decode(dest->local_label, &label, &ttl, &exp, &bos);
- p = bgp_dest_get_prefix(dest);
has_valid_label = bgp_is_valid_label(&label);
if (safi == SAFI_EVPN) {
@@ -11831,8 +11831,9 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
if (header) {
route_vty_out_detail_header(
- vty, bgp, bgp_node, pfx_rd,
- AFI_IP, safi, json_header);
+ vty, bgp, bgp_node,
+ bgp_dest_get_prefix(bgp_node), pfx_rd, AFI_IP,
+ safi, json_header);
header = 0;
}
(*display)++;
@@ -11843,8 +11844,10 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
|| (pathtype == BGP_PATH_SHOW_MULTIPATH
&& (CHECK_FLAG(pi->flags, BGP_PATH_MULTIPATH)
|| CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))))
- route_vty_out_detail(vty, bgp, bgp_node, pi, AFI_IP,
- safi, rpki_curr_state, json_paths);
+ route_vty_out_detail(vty, bgp, bgp_node,
+ bgp_dest_get_prefix(bgp_node), pi,
+ AFI_IP, safi, rpki_curr_state,
+ json_paths);
}
if (json && json_paths) {
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index ddef4ca1bb..48e1547166 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -214,9 +214,11 @@ struct bgp_path_info_extra {
} vnc;
#endif
- /* For imported routes into a VNI (or VRF), this points to the parent.
+ /*
+ * For imported routes into a VNI (or VRF)
*/
- void *parent;
+ void *parent; /* parent from global table */
+ struct ethaddr mac; /* MAC set here for VNI table */
/*
* Some tunnelish parameters follow. Maybe consolidate into an
@@ -827,10 +829,11 @@ extern bool bgp_zebra_has_route_changed(struct bgp_path_info *selected);
extern void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
struct bgp_dest *dest,
+ const struct prefix *p,
const struct prefix_rd *prd, afi_t afi,
safi_t safi, json_object *json);
extern void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
- struct bgp_dest *bn,
+ struct bgp_dest *bn, const struct prefix *p,
struct bgp_path_info *path, afi_t afi,
safi_t safi, enum rpki_states,
json_object *json_paths);