bgpd: Add CLI for overlay index recursive resolution

Gateway IP overlay index of the remote type-5 route is resolved
recursively using remote type-2 route. For the purpose of this
recursive resolution, for each L2VNI, we build a hash table of the
remote IP addresses received by remote type-2 routes.
For the topologies where overlay index resolution is not needed, we
do not need to build this remote-ip-hash.

Thus, make the recursive resolution of the overlay index conditional on
"enable-resolve-overlay-index" configuration.

router bgp 65001
 bgp router-id 192.168.100.1
 neighbor 10.0.1.2 remote-as 65002
!
 address-family l2vpn evpn
  neighbor 10.0.1.2 activate
  advertise-all-vni
  enable-resolve-overlay-index----------> New configuration
 exit-address-family

Gateway IP overlay index will be resolved only if this configuration is present.

Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
This commit is contained in:
Ameya Dharkar 2021-05-11 15:26:29 -07:00
parent 021b659665
commit dc6cef732e
4 changed files with 139 additions and 14 deletions

View File

@ -72,6 +72,10 @@ static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn,
struct bgp_path_info *pi);
static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn,
struct bgp_path_info *pi);
static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn,
void (*func)(struct hash_bucket *,
void *),
void *arg);
static void bgp_evpn_link_to_vni_svi_hash(struct bgp *bgp, struct bgpevpn *vpn);
static void bgp_evpn_unlink_from_vni_svi_hash(struct bgp *bgp,
struct bgpevpn *vpn);
@ -5780,9 +5784,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
* Unresolve all the gateway IP nexthops for this VNI
* for old SVI
*/
hash_iterate(vpn->remote_ip_hash,
(void (*)(struct hash_bucket *,
void *))bgp_evpn_remote_ip_hash_unlink_nexthop,
bgp_evpn_remote_ip_hash_iterate(
vpn,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_remote_ip_hash_unlink_nexthop,
vpn);
bgp_evpn_unlink_from_vni_svi_hash(bgp, vpn);
vpn->svi_ifindex = svi_ifindex;
@ -5792,9 +5797,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
* Resolve all the gateway IP nexthops for this VNI
* for new SVI
*/
hash_iterate(vpn->remote_ip_hash,
(void (*)(struct hash_bucket *,
void *))bgp_evpn_remote_ip_hash_link_nexthop,
bgp_evpn_remote_ip_hash_iterate(
vpn,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_remote_ip_hash_link_nexthop,
vpn);
}
@ -5805,9 +5811,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
* Unresolve all the gateway IP nexthops for this VNI
* in old tenant vrf
*/
hash_iterate(vpn->remote_ip_hash,
(void (*)(struct hash_bucket *,
void *))bgp_evpn_remote_ip_hash_unlink_nexthop,
bgp_evpn_remote_ip_hash_iterate(
vpn,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_remote_ip_hash_unlink_nexthop,
vpn);
bgpevpn_unlink_from_l3vni(vpn);
vpn->tenant_vrf_id = tenant_vrf_id;
@ -5817,9 +5824,10 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
* Resolve all the gateway IP nexthops for this VNI
* in new tenant vrf
*/
hash_iterate(vpn->remote_ip_hash,
(void (*)(struct hash_bucket *,
void *))bgp_evpn_remote_ip_hash_link_nexthop,
bgp_evpn_remote_ip_hash_iterate(
vpn,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_remote_ip_hash_link_nexthop,
vpn);
}
@ -6091,6 +6099,9 @@ static bool bgp_evpn_remote_ip_hash_cmp(const void *p1, const void *p2)
static void bgp_evpn_remote_ip_hash_init(struct bgpevpn *vpn)
{
if (!evpn_resolve_overlay_index())
return;
vpn->remote_ip_hash = hash_create(bgp_evpn_remote_ip_hash_key_make,
bgp_evpn_remote_ip_hash_cmp,
"BGP EVPN remote IP hash");
@ -6111,7 +6122,7 @@ static void bgp_evpn_remote_ip_hash_free(struct hash_bucket *bucket, void *args)
static void bgp_evpn_remote_ip_hash_destroy(struct bgpevpn *vpn)
{
if (vpn->remote_ip_hash == NULL)
if (!evpn_resolve_overlay_index() || vpn->remote_ip_hash == NULL)
return;
hash_iterate(vpn->remote_ip_hash,
@ -6130,6 +6141,13 @@ static void bgp_evpn_remote_ip_hash_add(struct bgpevpn *vpn,
struct evpn_remote_ip *ip;
struct prefix_evpn *evp;
if (!evpn_resolve_overlay_index())
return;
if (pi->type != ZEBRA_ROUTE_BGP || pi->sub_type != BGP_ROUTE_IMPORTED
|| !CHECK_FLAG(pi->flags, BGP_PATH_VALID))
return;
evp = (struct prefix_evpn *)&pi->net->p;
if (evp->family != AF_EVPN
@ -6163,6 +6181,9 @@ static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn,
struct evpn_remote_ip *ip;
struct prefix_evpn *evp;
if (!evpn_resolve_overlay_index())
return;
evp = (struct prefix_evpn *)&pi->net->p;
if (evp->family != AF_EVPN
@ -6184,6 +6205,17 @@ static void bgp_evpn_remote_ip_hash_del(struct bgpevpn *vpn,
}
}
static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn,
void (*func)(struct hash_bucket *,
void *),
void *arg)
{
if (!evpn_resolve_overlay_index())
return;
hash_iterate(vpn->remote_ip_hash, func, arg);
}
static void show_remote_ip_entry(struct hash_bucket *bucket, void *args)
{
char buf[INET6_ADDRSTRLEN];
@ -6211,7 +6243,8 @@ void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args)
struct vty *vty = (struct vty *)args;
vty_out(vty, "VNI: %u\n", vpn->vni);
hash_iterate(vpn->remote_ip_hash,
bgp_evpn_remote_ip_hash_iterate(
vpn,
(void (*)(struct hash_bucket *, void *))show_remote_ip_entry,
vty);
vty_out(vty, "\n");
@ -6300,6 +6333,9 @@ bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc)
struct evpn_remote_ip tmp;
struct prefix *p;
if (!evpn_resolve_overlay_index())
return false;
if (!bnc->nexthop || bnc->nexthop->ifindex == 0)
return false;
@ -6411,3 +6447,25 @@ static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn,
}
}
void bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket,
void *arg)
{
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
struct bgp_dest *dest;
struct bgp_path_info *pi;
bgp_evpn_remote_ip_hash_init(vpn);
for (dest = bgp_table_top(vpn->route_table); dest;
dest = bgp_route_next(dest))
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
bgp_evpn_remote_ip_hash_add(vpn, pi);
}
void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
void *arg)
{
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
bgp_evpn_remote_ip_hash_destroy(vpn);
}

View File

@ -156,6 +156,14 @@ static inline bool is_route_injectable_into_evpn(struct bgp_path_info *pi)
return true;
}
static inline bool evpn_resolve_overlay_index(void)
{
struct bgp *bgp = NULL;
bgp = bgp_get_evpn();
return bgp ? bgp->resolve_overlay_index : false;
}
extern void bgp_evpn_advertise_type5_route(struct bgp *bgp_vrf,
const struct prefix *p,
struct attr *src_attr, afi_t afi,
@ -215,5 +223,11 @@ extern void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket,
void *args);
extern void bgp_evpn_show_vni_svi_hash(struct hash_bucket *bucket, void *args);
extern bool bgp_evpn_is_gateway_ip_resolved(struct bgp_nexthop_cache *bnc);
extern void
bgp_evpn_handle_resolve_overlay_index_set(struct hash_bucket *bucket,
void *arg);
extern void
bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
void *arg);
#endif /* _QUAGGA_BGP_EVPN_H */

View File

@ -3302,6 +3302,28 @@ static void evpn_unset_advertise_all_vni(struct bgp *bgp)
bgp_evpn_cleanup_on_disable(bgp);
}
/* Set resolve overlay index flag */
static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
{
if (set == bgp->resolve_overlay_index)
return;
if (set) {
bgp->resolve_overlay_index = true;
hash_iterate(bgp->vnihash,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_handle_resolve_overlay_index_set,
NULL);
} else {
hash_iterate(
bgp->vnihash,
(void (*)(struct hash_bucket *, void *))
bgp_evpn_handle_resolve_overlay_index_unset,
NULL);
bgp->resolve_overlay_index = false;
}
}
/*
* EVPN - use RFC8365 to auto-derive RT
*/
@ -4117,6 +4139,23 @@ DEFPY (bgp_evpn_ead_evi_tx_disable,
return CMD_SUCCESS;
}
DEFPY (bgp_evpn_enable_resolve_overlay_index,
bgp_evpn_enable_resolve_overlay_index_cmd,
"[no$no] enable-resolve-overlay-index",
NO_STR
"Enable Recursive Resolution of type-5 route overlay index\n")
{
struct bgp *bgp = VTY_GET_CONTEXT(bgp);
if (bgp != bgp_get_evpn()) {
vty_out(vty, "This command is only supported under EVPN VRF\n");
return CMD_WARNING;
}
bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
return CMD_SUCCESS;
}
DEFPY (bgp_evpn_advertise_pip_ip_mac,
bgp_evpn_advertise_pip_ip_mac_cmd,
"[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
@ -6252,6 +6291,9 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
if (bgp->evpn_info->advertise_svi_macip)
vty_out(vty, " advertise-svi-ip\n");
if (bgp->resolve_overlay_index)
vty_out(vty, " enable-resolve-overlay-index\n");
if (bgp_mh_info->host_routes_use_l3nhg !=
BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
if (bgp_mh_info->host_routes_use_l3nhg)
@ -6440,6 +6482,8 @@ void bgp_ethernetvpn_init(void)
install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
install_element(BGP_EVPN_NODE,
&bgp_evpn_enable_resolve_overlay_index_cmd);
/* test commands */
install_element(BGP_EVPN_NODE, &test_es_add_cmd);

View File

@ -693,6 +693,15 @@ struct bgp {
/* Hash table of EVPN nexthops maintained per-tenant-VRF */
struct hash *evpn_nh_table;
/*
* Flag resolve_overlay_index is used for recursive resolution
* procedures for EVPN type-5 route's gateway IP overlay index.
* When this flag is set, we build remote-ip-hash for
* all L2VNIs and resolve overlay index nexthops using this hash.
* Overlay index nexthops remain unresolved if this flag is not set.
*/
bool resolve_overlay_index;
/* vrf flags */
uint32_t vrf_flags;
#define BGP_VRF_AUTO (1 << 0)