summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/if_netlink.c94
-rw-r--r--zebra/rt_netlink.c18
-rw-r--r--zebra/zebra_vxlan.c249
3 files changed, 236 insertions, 125 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.
*/
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 6fbe350435..25cd50eef2 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -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;
}
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 28ffafec5a..db231217b5 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -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);
-
- /* 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);
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("Building vni table for %s-if %s",
+ IS_ZEBRA_VXLAN_IF_VNI(zif) ? "vni" : "svd",
+ ifp->name);
- /*
- * 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;
}