mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-03 01:42:48 +00:00
bgpd: rework VNI table for type2/macip routes
Use the IP addr of type2/macip routes only for the hash/key of the VNI table and carry the MAC in a path_info_extra attribute. There is exists situations that can be hit during extended MAC mobility events where two MACs could be pointing to the same IP in our global table. It is requires very specific timings. When that happens, BPG would (because we key'd on both MAC and IP) install both into it's VNI table as separate entries, but zebra only knows/needs to know about a single IP -> MAC relationship for it's VNI table's type2 routes. So it was compleletly undeterministic which one zebra would end up with in these timing situations. With these changes, we move BGP's VNI table to key'd the same as Zebra's and now a single IP will have multiple path_info's with a path_info_extra that is carrying the MAC info for each path. BGP will then run best path to deterministically decide which one to send to zebra during the occasions where there exist's two possible MACs. Signed-off-by: Stephen Worley <sworley@nvidia.com>
This commit is contained in:
parent
7d99ad7f93
commit
34c7f35f02
284
bgpd/bgp_evpn.c
284
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,14 +2098,20 @@ 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;
|
||||
|
||||
if (CHECK_FLAG(local_pi->flags, BGP_PATH_REMOVED))
|
||||
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
|
||||
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user