bgpd, zebra: Add svi_interface to zebra VNI and bgp EVPN structures

SVI ifindex for L2VNI is required in BGP to perform EVPN type-5 to type-2
recusrsive resolution using gateway IP overlay index.

Program this svi_ifindex in struct zebra_vni_t as well as in struct bgpevpn

Changes include:
1. Add svi_if field to struct zebra_evpn_t
2. Add svi_ifindex field to struct bgpevpn
3. When SVI (bridge or VLAN) is bound to a VxLAN interface, store it in the
zebra_evpn_t structure.
4. Add this SVI ifindex to ZEBRA_VNI_ADD
5. Store svi_ifindex in struct bgpevpn

Signed-off-by: Ameya Dharkar <adharkar@vmware.com>
This commit is contained in:
Ameya Dharkar 2021-01-11 00:14:05 -08:00
parent a2299abae8
commit 9daa5d471a
8 changed files with 67 additions and 17 deletions

View File

@ -5230,7 +5230,8 @@ struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni)
struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
vrf_id_t tenant_vrf_id,
struct in_addr mcast_grp)
struct in_addr mcast_grp,
ifindex_t svi_ifindex)
{
struct bgpevpn *vpn;
@ -5244,6 +5245,7 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
vpn->originator_ip = originator_ip;
vpn->tenant_vrf_id = tenant_vrf_id;
vpn->mcast_grp = mcast_grp;
vpn->svi_ifindex = svi_ifindex;
/* Initialize route-target import and export lists */
vpn->import_rtl = list_new();
@ -5699,6 +5701,7 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
*/
delete_routes_for_vni(bgp, vpn);
vpn->svi_ifindex = 0;
/*
* tunnel is no longer active, del tunnel ip address from tip_hash
*/
@ -5719,8 +5722,8 @@ int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
vrf_id_t tenant_vrf_id,
struct in_addr mcast_grp)
struct in_addr mcast_grp,
ifindex_t svi_ifindex)
{
struct bgpevpn *vpn;
struct prefix_evpn p;
@ -5732,13 +5735,16 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
if (is_vni_live(vpn)
&& IPV4_ADDR_SAME(&vpn->originator_ip, &originator_ip)
&& IPV4_ADDR_SAME(&vpn->mcast_grp, &mcast_grp)
&& vpn->tenant_vrf_id == tenant_vrf_id)
&& vpn->tenant_vrf_id == tenant_vrf_id
&& vpn->svi_ifindex == svi_ifindex)
/* Probably some other param has changed that we don't
* care about. */
return 0;
bgp_evpn_mcast_grp_change(bgp, vpn, mcast_grp);
vpn->svi_ifindex = svi_ifindex;
/* Update tenant_vrf_id if it has changed. */
if (vpn->tenant_vrf_id != tenant_vrf_id) {
bgpevpn_unlink_from_l3vni(vpn);
@ -5762,7 +5768,7 @@ int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
/* Create or update as appropriate. */
if (!vpn) {
vpn = bgp_evpn_new(bgp, vni, originator_ip, tenant_vrf_id,
mcast_grp);
mcast_grp, svi_ifindex);
if (!vpn) {
flog_err(
EC_BGP_VNI,

View File

@ -202,7 +202,8 @@ extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
vrf_id_t tenant_vrf_id,
struct in_addr mcast_grp);
struct in_addr mcast_grp,
ifindex_t svi_ifindex);
extern void bgp_evpn_flood_control_change(struct bgp *bgp);
extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp);
extern void bgp_evpn_cleanup(struct bgp *bgp);

View File

@ -62,6 +62,7 @@ RB_PROTOTYPE(bgp_es_evi_rb_head, bgp_evpn_es_evi, rb_node,
struct bgpevpn {
vni_t vni;
vrf_id_t tenant_vrf_id;
ifindex_t svi_ifindex;
uint32_t flags;
#define VNI_FLAG_CFGD 0x1 /* VNI is user configured */
#define VNI_FLAG_LIVE 0x2 /* VNI is "live" */
@ -612,7 +613,8 @@ extern struct bgpevpn *bgp_evpn_lookup_vni(struct bgp *bgp, vni_t vni);
extern struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
vrf_id_t tenant_vrf_id,
struct in_addr mcast_grp);
struct in_addr mcast_grp,
ifindex_t svi_ifindex);
extern void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn);
extern bool bgp_evpn_lookup_l3vni_l2vni_table(vni_t vni);
extern int update_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn);

View File

@ -531,6 +531,9 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
else
json_object_string_add(json, "advertiseSviMacIp",
"Disabled");
json_object_string_add(
json, "sviInterface",
ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
} else {
vty_out(vty, "VNI: %d", vpn->vni);
if (is_vni_live(vpn))
@ -564,6 +567,8 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
else
vty_out(vty, " Advertise-svi-macip : %s\n",
"Disabled");
vty_out(vty, " SVI interface : %s\n",
ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
}
if (!json)
@ -2290,7 +2295,7 @@ static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
/* tenant vrf will be updated when we get local_vni_add from
* zebra
*/
vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp);
vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp, 0);
if (!vpn) {
flog_err(
EC_BGP_VNI,

View File

@ -2830,6 +2830,7 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS)
struct in_addr vtep_ip = {INADDR_ANY};
vrf_id_t tenant_vrf_id = VRF_DEFAULT;
struct in_addr mcast_grp = {INADDR_ANY};
ifindex_t svi_ifindex = 0;
s = zclient->ibuf;
vni = stream_getl(s);
@ -2837,6 +2838,7 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS)
vtep_ip.s_addr = stream_get_ipv4(s);
stream_get(&tenant_vrf_id, s, sizeof(vrf_id_t));
mcast_grp.s_addr = stream_get_ipv4(s);
stream_get(&svi_ifindex, s, sizeof(ifindex_t));
}
bgp = bgp_lookup_by_vrf_id(vrf_id);
@ -2844,16 +2846,17 @@ static int bgp_zebra_process_local_vni(ZAPI_CALLBACK_ARGS)
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx VNI %s VRF %s VNI %u tenant-vrf %s",
(cmd == ZEBRA_VNI_ADD) ? "add" : "del",
vrf_id_to_name(vrf_id), vni,
vrf_id_to_name(tenant_vrf_id));
zlog_debug(
"Rx VNI %s VRF %s VNI %u tenant-vrf %s SVI ifindex %u",
(cmd == ZEBRA_VNI_ADD) ? "add" : "del",
vrf_id_to_name(vrf_id), vni,
vrf_id_to_name(tenant_vrf_id), svi_ifindex);
if (cmd == ZEBRA_VNI_ADD)
return bgp_evpn_local_vni_add(
bgp, vni,
vtep_ip.s_addr != INADDR_ANY ? vtep_ip : bgp->router_id,
tenant_vrf_id, mcast_grp);
tenant_vrf_id, mcast_grp, svi_ifindex);
else
return bgp_evpn_local_vni_del(bgp, vni);
}

View File

@ -134,6 +134,10 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
if (json == NULL) {
vty_out(vty, " VxLAN interface: %s\n", zevpn->vxlan_if->name);
vty_out(vty, " VxLAN ifIndex: %u\n", zevpn->vxlan_if->ifindex);
vty_out(vty, " SVI interface: %s\n",
(zevpn->svi_if ? zevpn->svi_if->name : ""));
vty_out(vty, " SVI ifIndex: %u\n",
(zevpn->svi_if ? zevpn->svi_if->ifindex : 0));
vty_out(vty, " Local VTEP IP: %pI4\n",
&zevpn->local_vtep_ip);
vty_out(vty, " Mcast group: %pI4\n",
@ -142,6 +146,12 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
json_object_string_add(json, "vxlanInterface",
zevpn->vxlan_if->name);
json_object_int_add(json, "ifindex", zevpn->vxlan_if->ifindex);
if (zevpn->svi_if) {
json_object_string_add(json, "sviInterface",
zevpn->svi_if->name);
json_object_int_add(json, "sviIfindex",
zevpn->svi_if->ifindex);
}
json_object_string_add(json, "vtepIp",
inet_ntop(AF_INET, &zevpn->local_vtep_ip,
buf, sizeof(buf)));
@ -1048,6 +1058,8 @@ int zebra_evpn_del(zebra_evpn_t *zevpn)
zvrf = zebra_vrf_get_evpn();
assert(zvrf);
zevpn->svi_if = NULL;
/* Free the neighbor hash table. */
hash_free(zevpn->neigh_table);
zevpn->neigh_table = NULL;
@ -1075,6 +1087,7 @@ int zebra_evpn_send_add_to_client(zebra_evpn_t *zevpn)
{
struct zserv *client;
struct stream *s;
ifindex_t svi_index;
int rc;
client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
@ -1082,6 +1095,8 @@ int zebra_evpn_send_add_to_client(zebra_evpn_t *zevpn)
if (!client)
return 0;
svi_index = zevpn->svi_if ? zevpn->svi_if->ifindex : 0;
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id());
@ -1089,15 +1104,18 @@ int zebra_evpn_send_add_to_client(zebra_evpn_t *zevpn)
stream_put_in_addr(s, &zevpn->local_vtep_ip);
stream_put(s, &zevpn->vrf_id, sizeof(vrf_id_t)); /* tenant vrf */
stream_put_in_addr(s, &zevpn->mcast_grp);
stream_put(s, &svi_index, sizeof(ifindex_t));
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug("Send EVPN_ADD %u %pI4 tenant vrf %s to %s", zevpn->vni,
&zevpn->local_vtep_ip,
vrf_id_to_name(zevpn->vrf_id),
zebra_route_string(client->proto));
zlog_debug(
"Send EVPN_ADD %u %pI4 tenant vrf %s(%u) SVI index %u to %s",
zevpn->vni, &zevpn->local_vtep_ip,
vrf_id_to_name(zevpn->vrf_id), zevpn->vrf_id,
(zevpn->svi_if ? zevpn->svi_if->ifindex : 0),
zebra_route_string(client->proto));
client->vniadd_cnt++;
rc = zserv_send_message(client, s);

View File

@ -98,6 +98,9 @@ struct zebra_evpn_t_ {
/* Corresponding VxLAN interface. */
struct interface *vxlan_if;
/* Corresponding SVI interface. */
struct interface *svi_if;
/* List of remote VTEPs */
zebra_vtep_t *vteps;

View File

@ -1012,6 +1012,7 @@ static int zevpn_build_hash_table_zns(struct ns *ns,
vxl->access_vlan,
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
zevpn->vrf_id = vlan_if->vrf_id;
zl3vni = zl3vni_from_vrf(
vlan_if->vrf_id);
@ -4527,6 +4528,7 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
zevpn = zebra_evpn_from_svi(ifp, link_if);
if (zevpn) {
zevpn->svi_if = NULL;
zevpn->vrf_id = VRF_DEFAULT;
/* update the tenant vrf in BGP */
@ -4582,6 +4584,7 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
vrf_id_to_name(ifp->vrf_id));
/* update the vrf information for l2-vni and inform bgp */
zevpn->svi_if = ifp;
zevpn->vrf_id = ifp->vrf_id;
if (if_is_operative(zevpn->vxlan_if))
@ -4792,6 +4795,7 @@ int zebra_vxlan_if_up(struct interface *ifp)
vlan_if = zvni_map_to_svi(vxl->access_vlan,
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
zevpn->vrf_id = vlan_if->vrf_id;
zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
if (zl3vni)
@ -4894,6 +4898,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
struct zebra_l2info_vxlan *vxl = NULL;
zebra_evpn_t *zevpn = NULL;
zebra_l3vni_t *zl3vni = NULL;
struct interface *vlan_if = NULL;
/* Check if EVPN is enabled. */
if (!is_evpn_enabled())
@ -4983,6 +4988,7 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
&& (zif->brslave_info.bridge_ifindex == IFINDEX_INTERNAL)) {
/* Delete from client, remove all remote VTEPs */
/* Also, free up all MACs and neighbors. */
zevpn->svi_if = NULL;
zebra_evpn_send_del_to_client(zevpn);
zebra_evpn_neigh_del_all(zevpn, 1, 0, DEL_ALL_NEIGH);
zebra_evpn_mac_del_all(zevpn, 1, 0, DEL_ALL_MAC);
@ -5012,6 +5018,11 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
zebra_evpn_es_set_base_evpn(zevpn);
}
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
vlan_if = zvni_map_to_svi(vxl->access_vlan,
zif->brslave_info.br_if);
if (vlan_if)
zevpn->svi_if = vlan_if;
/* Take further actions needed.
* Note that if we are here, there is a change of interest.
*/
@ -5131,6 +5142,7 @@ int zebra_vxlan_if_add(struct interface *ifp)
vlan_if = zvni_map_to_svi(vxl->access_vlan,
zif->brslave_info.br_if);
if (vlan_if) {
zevpn->svi_if = vlan_if;
zevpn->vrf_id = vlan_if->vrf_id;
zl3vni = zl3vni_from_vrf(vlan_if->vrf_id);
if (zl3vni)