forked from Mirror/frr
zebra: single vxlan device vni handling
This change brings in following functionality - netlink_bridge_vxlan_vlan_vni_map_update for single vxlan devices This function is responsible for reading the vlan-vni map information received from netlink and populating a new hash_table with the vlan-vni data. Once all the vlan-vni data is collected, zebra_vxlan_if_vni_table_add_update is called to update vni_table in vxlan interface and process each of the vlan-vni data. - refactoring changes for zevpn_build_hash_table - existing zevpn_build_hash_table was walking over all the vxlan interfaces and then processing the vni for each of them. In case of single vxlan device, we will have more than one vni entries. This function is abstracted so that it iterates over all the vni entries for single vxlan device. For traditional vxlan device the zebra_vxlan_if_vni_iterate would only process single vni associated with that device. Signed-off-by: Sharath Ramamurthy <sramamurthy@nvidia.com>
This commit is contained in:
parent
96c25556a1
commit
131a9a2eed
|
@ -720,16 +720,110 @@ static void netlink_interface_update_l2info(struct interface *ifp,
|
|||
}
|
||||
}
|
||||
|
||||
static int netlink_bridge_vxlan_vlan_vni_map_update(struct interface *ifp,
|
||||
struct rtattr *af_spec)
|
||||
{
|
||||
int rem;
|
||||
vni_t vni_id;
|
||||
vlanid_t vid;
|
||||
uint16_t flags;
|
||||
struct rtattr *i;
|
||||
struct zebra_vxlan_vni vni;
|
||||
struct zebra_vxlan_vni *vnip;
|
||||
struct hash *vni_table = NULL;
|
||||
struct zebra_vxlan_vni vni_end;
|
||||
struct zebra_vxlan_vni vni_start;
|
||||
struct rtattr *aftb[IFLA_BRIDGE_VLAN_TUNNEL_MAX + 1];
|
||||
|
||||
for (i = RTA_DATA(af_spec), rem = RTA_PAYLOAD(af_spec); RTA_OK(i, rem);
|
||||
i = RTA_NEXT(i, rem)) {
|
||||
|
||||
if (i->rta_type != IFLA_BRIDGE_VLAN_TUNNEL_INFO)
|
||||
continue;
|
||||
|
||||
memset(aftb, 0, sizeof(aftb));
|
||||
netlink_parse_rtattr_nested(aftb, IFLA_BRIDGE_VLAN_TUNNEL_MAX,
|
||||
i);
|
||||
if (!aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID]
|
||||
|| !aftb[IFLA_BRIDGE_VLAN_TUNNEL_VID])
|
||||
/* vlan-vni info missing */
|
||||
return 0;
|
||||
|
||||
flags = 0;
|
||||
memset(&vni, 0, sizeof(vni));
|
||||
|
||||
vni.vni = *(vni_t *)RTA_DATA(aftb[IFLA_BRIDGE_VLAN_TUNNEL_ID]);
|
||||
vni.access_vlan = *(vlanid_t *)RTA_DATA(
|
||||
aftb[IFLA_BRIDGE_VLAN_TUNNEL_VID]);
|
||||
|
||||
if (aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS])
|
||||
flags = *(uint16_t *)RTA_DATA(
|
||||
aftb[IFLA_BRIDGE_VLAN_TUNNEL_FLAGS]);
|
||||
|
||||
if (flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
|
||||
vni_start = vni;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flags & BRIDGE_VLAN_INFO_RANGE_END)
|
||||
vni_end = vni;
|
||||
|
||||
if (!(flags & BRIDGE_VLAN_INFO_RANGE_END)) {
|
||||
vni_start = vni;
|
||||
vni_end = vni;
|
||||
}
|
||||
|
||||
if (IS_ZEBRA_DEBUG_KERNEL)
|
||||
zlog_debug(
|
||||
"Vlan-Vni(%d:%d-%d:%d) update for VxLAN IF %s(%u)",
|
||||
vni_start.access_vlan, vni_end.access_vlan,
|
||||
vni_start.vni, vni_end.vni, ifp->name,
|
||||
ifp->ifindex);
|
||||
|
||||
if (!vni_table) {
|
||||
vni_table = zebra_vxlan_vni_table_create();
|
||||
if (!vni_table)
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (vid = vni_start.access_vlan, vni_id = vni_start.vni;
|
||||
vid <= vni_end.access_vlan; vid++, vni_id++) {
|
||||
|
||||
memset(&vni, 0, sizeof(vni));
|
||||
vni.vni = vni_id;
|
||||
vni.access_vlan = vid;
|
||||
vnip = hash_get(vni_table, &vni, zebra_vxlan_vni_alloc);
|
||||
if (!vnip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(&vni_start, 0, sizeof(vni_start));
|
||||
memset(&vni_end, 0, sizeof(vni_end));
|
||||
}
|
||||
|
||||
if (vni_table)
|
||||
zebra_vxlan_if_vni_table_add_update(ifp, vni_table);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int netlink_bridge_vxlan_update(struct interface *ifp,
|
||||
struct rtattr *af_spec)
|
||||
{
|
||||
struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
|
||||
struct bridge_vlan_info *vinfo;
|
||||
struct zebra_if *zif;
|
||||
vlanid_t access_vlan;
|
||||
|
||||
if (!af_spec)
|
||||
return 0;
|
||||
|
||||
zif = (struct zebra_if *)ifp->info;
|
||||
|
||||
/* Single vxlan devices has vni-vlan range to update */
|
||||
if (IS_ZEBRA_VXLAN_IF_SVD(zif))
|
||||
return netlink_bridge_vxlan_vlan_vni_map_update(ifp, af_spec);
|
||||
|
||||
/* There is a 1-to-1 mapping of VLAN to VxLAN - hence
|
||||
* only 1 access VLAN is accepted.
|
||||
*/
|
||||
|
|
|
@ -3633,12 +3633,12 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
|
|||
return 0;
|
||||
|
||||
if (vni_mcast_grp)
|
||||
/* TODO: handle mcast group update for svd */
|
||||
return zebra_vxlan_if_vni_mcast_group_update(
|
||||
ifp, vni, &vtep_ip);
|
||||
|
||||
return zebra_vxlan_dp_network_mac_add(
|
||||
ifp, br_if, &mac, vid, vni, nhg_id,
|
||||
sticky,
|
||||
!!(ndm->ndm_flags & NTF_EXT_LEARNED));
|
||||
return zebra_vxlan_dp_network_mac_add(
|
||||
ifp, br_if, &mac, vid, vni, nhg_id, sticky,
|
||||
!!(ndm->ndm_flags & NTF_EXT_LEARNED));
|
||||
}
|
||||
|
||||
return zebra_vxlan_local_mac_add_update(ifp, br_if, &mac, vid,
|
||||
|
@ -3660,11 +3660,11 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
|
|||
|
||||
if (dst_present) {
|
||||
if (vni_mcast_grp)
|
||||
/* TODO: handle mcast group update for svd */
|
||||
return zebra_vxlan_if_vni_mcast_group_update(ifp, vni,
|
||||
NULL);
|
||||
|
||||
if (is_zero_mac(&mac))
|
||||
return zebra_vxlan_check_readd_vtep(ifp, vni,
|
||||
vtep_ip);
|
||||
if (is_zero_mac(&mac))
|
||||
return zebra_vxlan_check_readd_vtep(ifp, vni, vtep_ip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -917,6 +917,131 @@ int zebra_evpn_vxlan_del(struct zebra_evpn *zevpn)
|
|||
return zebra_evpn_del(zevpn);
|
||||
}
|
||||
|
||||
static int zevpn_build_vni_hash_table(struct zebra_if *zif,
|
||||
struct zebra_vxlan_vni *vnip, void *arg)
|
||||
{
|
||||
vni_t vni;
|
||||
struct zebra_evpn *zevpn;
|
||||
struct zebra_l3vni *zl3vni;
|
||||
struct interface *ifp;
|
||||
struct zebra_l2info_vxlan *vxl;
|
||||
|
||||
ifp = zif->ifp;
|
||||
vxl = &zif->l2info.vxl;
|
||||
vni = vnip->vni;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("Build vni table for vni %u for Intf %s", vni,
|
||||
ifp->name);
|
||||
|
||||
/* L3-VNI and L2-VNI are handled seperately */
|
||||
zl3vni = zl3vni_lookup(vni);
|
||||
if (zl3vni) {
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"create L3-VNI hash for Intf %s(%u) L3-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
|
||||
/* associate with vxlan_if */
|
||||
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
||||
zl3vni->vxlan_if = ifp;
|
||||
|
||||
/*
|
||||
* we need to associate with SVI.
|
||||
* we can associate with svi-if only after association
|
||||
* with vxlan-intf is complete
|
||||
*/
|
||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||
|
||||
/* Associate l3vni to mac-vlan and extract VRR MAC */
|
||||
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"create l3vni %u svi_if %s mac_vlan_if %s", vni,
|
||||
zl3vni->svi_if ? zl3vni->svi_if->name : "NIL",
|
||||
zl3vni->mac_vlan_if ? zl3vni->mac_vlan_if->name
|
||||
: "NIL");
|
||||
|
||||
if (is_l3vni_oper_up(zl3vni))
|
||||
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
||||
|
||||
} else {
|
||||
struct interface *vlan_if = NULL;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
|
||||
ifp->name, ifp->ifindex, vni, &vxl->vtep_ip);
|
||||
|
||||
/* EVPN hash entry is expected to exist, if the BGP process is
|
||||
* killed */
|
||||
zevpn = zebra_evpn_lookup(vni);
|
||||
if (zevpn) {
|
||||
zlog_debug(
|
||||
"EVPN hash already present for IF %s(%u) L2-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
|
||||
/*
|
||||
* Inform BGP if intf is up and mapped to
|
||||
* bridge.
|
||||
*/
|
||||
if (if_is_operative(ifp) && zif->brslave_info.br_if)
|
||||
zebra_evpn_send_add_to_client(zevpn);
|
||||
|
||||
/* Send Local MAC-entries to client */
|
||||
zebra_evpn_send_mac_list_to_client(zevpn);
|
||||
|
||||
/* Send Loval Neighbor entries to client */
|
||||
zebra_evpn_send_neigh_to_client(zevpn);
|
||||
} else {
|
||||
zevpn = zebra_evpn_add(vni);
|
||||
if (!zevpn) {
|
||||
zlog_debug(
|
||||
"Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (zevpn->local_vtep_ip.s_addr != vxl->vtep_ip.s_addr
|
||||
|| zevpn->mcast_grp.s_addr
|
||||
!= vnip->mcast_grp.s_addr) {
|
||||
zebra_vxlan_sg_deref(zevpn->local_vtep_ip,
|
||||
zevpn->mcast_grp);
|
||||
zebra_vxlan_sg_ref(vxl->vtep_ip,
|
||||
vnip->mcast_grp);
|
||||
zevpn->local_vtep_ip = vxl->vtep_ip;
|
||||
zevpn->mcast_grp = vnip->mcast_grp;
|
||||
/* on local vtep-ip check if ES
|
||||
* orig-ip needs to be updated
|
||||
*/
|
||||
zebra_evpn_es_set_base_evpn(zevpn);
|
||||
}
|
||||
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
|
||||
vlan_if = zvni_map_to_svi(vnip->access_vlan,
|
||||
zif->brslave_info.br_if);
|
||||
if (vlan_if) {
|
||||
zevpn->svi_if = vlan_if;
|
||||
zevpn->vrf_id = vlan_if->vrf->vrf_id;
|
||||
zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
|
||||
if (zl3vni)
|
||||
listnode_add_sort(zl3vni->l2vnis,
|
||||
zevpn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform BGP if intf is up and mapped to
|
||||
* bridge.
|
||||
*/
|
||||
if (if_is_operative(ifp) && zif->brslave_info.br_if)
|
||||
zebra_evpn_send_add_to_client(zevpn);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zevpn_build_hash_table_zns(struct ns *ns,
|
||||
void *param_in __attribute__((unused)),
|
||||
void **param_out __attribute__((unused)))
|
||||
|
@ -930,12 +1055,8 @@ static int zevpn_build_hash_table_zns(struct ns *ns,
|
|||
|
||||
/* Walk VxLAN interfaces and create EVPN hash. */
|
||||
for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
|
||||
vni_t vni;
|
||||
struct zebra_evpn *zevpn = NULL;
|
||||
struct zebra_l3vni *zl3vni = NULL;
|
||||
struct zebra_if *zif;
|
||||
struct zebra_l2info_vxlan *vxl;
|
||||
struct zebra_vxlan_vni *vnip;
|
||||
|
||||
ifp = (struct interface *)rn->info;
|
||||
if (!ifp)
|
||||
|
@ -945,127 +1066,23 @@ static int zevpn_build_hash_table_zns(struct ns *ns,
|
|||
continue;
|
||||
|
||||
vxl = &zif->l2info.vxl;
|
||||
vnip = zebra_vxlan_if_vni_find(zif, 0);
|
||||
vni = vnip->vni;
|
||||
/* link of VXLAN interface should be in zebra_evpn_vrf */
|
||||
if (zvrf->zns->ns_id != vxl->link_nsid) {
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Intf %s(%u) VNI %u, link not in same "
|
||||
"Intf %s(%u) link not in same "
|
||||
"namespace than BGP EVPN core instance ",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
ifp->name, ifp->ifindex);
|
||||
continue;
|
||||
}
|
||||
/* L3-VNI and L2-VNI are handled seperately */
|
||||
zl3vni = zl3vni_lookup(vni);
|
||||
if (zl3vni) {
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"create L3-VNI hash for Intf %s(%u) L3-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("Building vni table for %s-if %s",
|
||||
IS_ZEBRA_VXLAN_IF_VNI(zif) ? "vni" : "svd",
|
||||
ifp->name);
|
||||
|
||||
/* associate with vxlan_if */
|
||||
zl3vni->local_vtep_ip = vxl->vtep_ip;
|
||||
zl3vni->vxlan_if = ifp;
|
||||
|
||||
/*
|
||||
* we need to associate with SVI.
|
||||
* we can associate with svi-if only after association
|
||||
* with vxlan-intf is complete
|
||||
*/
|
||||
zl3vni->svi_if = zl3vni_map_to_svi_if(zl3vni);
|
||||
|
||||
/* Associate l3vni to mac-vlan and extract VRR MAC */
|
||||
zl3vni->mac_vlan_if = zl3vni_map_to_mac_vlan_if(zl3vni);
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug("create l3vni %u svi_if %s mac_vlan_if %s",
|
||||
vni, zl3vni->svi_if ? zl3vni->svi_if->name
|
||||
: "NIL",
|
||||
zl3vni->mac_vlan_if ?
|
||||
zl3vni->mac_vlan_if->name : "NIL");
|
||||
|
||||
if (is_l3vni_oper_up(zl3vni))
|
||||
zebra_vxlan_process_l3vni_oper_up(zl3vni);
|
||||
|
||||
} else {
|
||||
struct interface *vlan_if = NULL;
|
||||
|
||||
if (IS_ZEBRA_DEBUG_VXLAN)
|
||||
zlog_debug(
|
||||
"Create L2-VNI hash for intf %s(%u) L2-VNI %u local IP %pI4",
|
||||
ifp->name, ifp->ifindex, vni,
|
||||
&vxl->vtep_ip);
|
||||
|
||||
/* EVPN hash entry is expected to exist, if the BGP process is killed */
|
||||
zevpn = zebra_evpn_lookup(vni);
|
||||
if (zevpn) {
|
||||
zlog_debug(
|
||||
"EVPN hash already present for IF %s(%u) L2-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
|
||||
/*
|
||||
* Inform BGP if intf is up and mapped to
|
||||
* bridge.
|
||||
*/
|
||||
if (if_is_operative(ifp) &&
|
||||
zif->brslave_info.br_if)
|
||||
zebra_evpn_send_add_to_client(zevpn);
|
||||
|
||||
/* Send Local MAC-entries to client */
|
||||
zebra_evpn_send_mac_list_to_client(zevpn);
|
||||
|
||||
/* Send Loval Neighbor entries to client */
|
||||
zebra_evpn_send_neigh_to_client(zevpn);
|
||||
} else {
|
||||
zevpn = zebra_evpn_add(vni);
|
||||
if (!zevpn) {
|
||||
zlog_debug(
|
||||
"Failed to add EVPN hash, IF %s(%u) L2-VNI %u",
|
||||
ifp->name, ifp->ifindex, vni);
|
||||
return NS_WALK_CONTINUE;
|
||||
}
|
||||
|
||||
if (zevpn->local_vtep_ip.s_addr
|
||||
!= vxl->vtep_ip.s_addr
|
||||
|| zevpn->mcast_grp.s_addr
|
||||
!= vnip->mcast_grp.s_addr) {
|
||||
zebra_vxlan_sg_deref(
|
||||
zevpn->local_vtep_ip,
|
||||
zevpn->mcast_grp);
|
||||
zebra_vxlan_sg_ref(vxl->vtep_ip,
|
||||
vnip->mcast_grp);
|
||||
zevpn->local_vtep_ip = vxl->vtep_ip;
|
||||
zevpn->mcast_grp = vnip->mcast_grp;
|
||||
/* on local vtep-ip check if ES
|
||||
* orig-ip needs to be updated
|
||||
*/
|
||||
zebra_evpn_es_set_base_evpn(zevpn);
|
||||
}
|
||||
zevpn_vxlan_if_set(zevpn, ifp, true /* set */);
|
||||
vlan_if = zvni_map_to_svi(
|
||||
vnip->access_vlan,
|
||||
zif->brslave_info.br_if);
|
||||
if (vlan_if) {
|
||||
zevpn->svi_if = vlan_if;
|
||||
zevpn->vrf_id = vlan_if->vrf->vrf_id;
|
||||
zl3vni = zl3vni_from_vrf(
|
||||
vlan_if->vrf->vrf_id);
|
||||
if (zl3vni)
|
||||
listnode_add_sort(
|
||||
zl3vni->l2vnis, zevpn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inform BGP if intf is up and mapped to
|
||||
* bridge.
|
||||
*/
|
||||
if (if_is_operative(ifp) &&
|
||||
zif->brslave_info.br_if)
|
||||
zebra_evpn_send_add_to_client(zevpn);
|
||||
}
|
||||
}
|
||||
zebra_vxlan_if_vni_iterate(zif, zevpn_build_vni_hash_table,
|
||||
NULL);
|
||||
}
|
||||
return NS_WALK_CONTINUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue