summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zebra/if_netlink.c127
1 files changed, 102 insertions, 25 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 4e85ce7d02..81f77d4f9b 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -70,6 +70,7 @@
#include "zebra/if_netlink.h"
#include "zebra/zebra_errors.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_evpn_mh.h"
extern struct zebra_privs_t zserv_privs;
@@ -245,6 +246,26 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
}
}
+static inline void zebra_if_set_ziftype(struct interface *ifp,
+ zebra_iftype_t zif_type,
+ zebra_slave_iftype_t zif_slave_type)
+{
+ struct zebra_if *zif;
+
+ zif = (struct zebra_if *)ifp->info;
+ zif->zif_slave_type = zif_slave_type;
+
+ if (zif->zif_type != zif_type) {
+ zif->zif_type = zif_type;
+ /* If the if_type has been set to bond initialize ES info
+ * against it. XXX - note that we don't handle the case where
+ * a zif changes from bond to non-bond; it is really
+ * an unexpected/error condition.
+ */
+ zebra_evpn_if_init(zif);
+ }
+}
+
static void netlink_determine_zebra_iftype(const char *kind,
zebra_iftype_t *zif_type)
{
@@ -557,6 +578,74 @@ static void netlink_interface_update_l2info(struct interface *ifp,
}
}
+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;
+ vlanid_t access_vlan;
+
+ /* There is a 1-to-1 mapping of VLAN to VxLAN - hence
+ * only 1 access VLAN is accepted.
+ */
+ memset(aftb, 0, sizeof(aftb));
+ parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, af_spec);
+ if (!aftb[IFLA_BRIDGE_VLAN_INFO])
+ return 0;
+
+ vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
+ if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
+ return 0;
+
+ access_vlan = (vlanid_t)vinfo->vid;
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan,
+ ifp->name, ifp->ifindex);
+ zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan);
+ return 0;
+}
+
+static void netlink_bridge_vlan_update(struct interface *ifp,
+ struct rtattr *af_spec)
+{
+ struct rtattr *i;
+ int rem;
+ uint16_t vid_range_start = 0;
+ struct zebra_if *zif;
+ bitfield_t old_vlan_bitmap;
+ struct bridge_vlan_info *vinfo;
+
+ zif = (struct zebra_if *)ifp->info;
+
+ /* cache the old bitmap addrs */
+ old_vlan_bitmap = zif->vlan_bitmap;
+ /* create a new bitmap space for re-eval */
+ bf_init(zif->vlan_bitmap, IF_VLAN_BITMAP_MAX);
+
+ 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_INFO)
+ continue;
+
+ vinfo = RTA_DATA(i);
+
+ if (vinfo->flags & BRIDGE_VLAN_INFO_RANGE_BEGIN) {
+ vid_range_start = vinfo->vid;
+ continue;
+ }
+
+ if (!(vinfo->flags & BRIDGE_VLAN_INFO_RANGE_END))
+ vid_range_start = vinfo->vid;
+
+ zebra_vlan_bitmap_compute(ifp, vid_range_start, vinfo->vid);
+ }
+
+ zebra_vlan_mbr_re_eval(ifp, old_vlan_bitmap);
+
+ bf_free(old_vlan_bitmap);
+}
+
static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
int startup)
{
@@ -564,12 +653,8 @@ static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
struct ifinfomsg *ifi;
struct rtattr *tb[IFLA_MAX + 1];
struct interface *ifp;
- struct rtattr *aftb[IFLA_BRIDGE_MAX + 1];
- struct {
- uint16_t flags;
- uint16_t vid;
- } * vinfo;
- vlanid_t access_vlan;
+ struct zebra_if *zif;
+ struct rtattr *af_spec;
/* Fetch name and ifindex */
ifi = NLMSG_DATA(h);
@@ -587,30 +672,22 @@ static int netlink_bridge_interface(struct nlmsghdr *h, int len, ns_id_t ns_id,
ifi->ifi_index);
return 0;
}
- if (!IS_ZEBRA_IF_VXLAN(ifp))
- return 0;
/* We are only interested in the access VLAN i.e., AF_SPEC */
- if (!tb[IFLA_AF_SPEC])
- return 0;
+ af_spec = tb[IFLA_AF_SPEC];
+ if (!af_spec)
+ return 0;
- /* There is a 1-to-1 mapping of VLAN to VxLAN - hence
- * only 1 access VLAN is accepted.
- */
- memset(aftb, 0, sizeof(aftb));
- parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]);
- if (!aftb[IFLA_BRIDGE_VLAN_INFO])
- return 0;
+ if (IS_ZEBRA_IF_VXLAN(ifp))
+ return netlink_bridge_vxlan_update(ifp, af_spec);
- vinfo = RTA_DATA(aftb[IFLA_BRIDGE_VLAN_INFO]);
- if (!(vinfo->flags & BRIDGE_VLAN_INFO_PVID))
- return 0;
+ /* build vlan bitmap associated with this interface if that
+ * device type is interested in the vlans
+ */
+ zif = (struct zebra_if *)ifp->info;
+ if (bf_is_inited(zif->vlan_bitmap))
+ netlink_bridge_vlan_update(ifp, af_spec);
- access_vlan = (vlanid_t)vinfo->vid;
- if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Access VLAN %u for VxLAN IF %s(%u)", access_vlan,
- name, ifi->ifi_index);
- zebra_l2_vxlanif_update_access_vlan(ifp, access_vlan);
return 0;
}