summaryrefslogtreecommitdiff
path: root/zebra/if_netlink.c
diff options
context:
space:
mode:
authorSharath Ramamurthy <sramamurthy@nvidia.com>2021-07-27 14:18:05 +0530
committerStephen Worley <sworley@nvidia.com>2023-02-13 18:12:04 -0500
commit131a9a2eeddab0f528b4ad6d29f0f4081cf8d8fe (patch)
tree5965f885921d2902e69e222e3b96a7b4a1e8862c /zebra/if_netlink.c
parent96c25556a1c1660d2a4f852ff7ab14e698d4387c (diff)
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>
Diffstat (limited to 'zebra/if_netlink.c')
-rw-r--r--zebra/if_netlink.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 3b4e048aff..6375fc1bd0 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -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.
*/