diff options
Diffstat (limited to 'zebra/if_netlink.c')
| -rw-r--r-- | zebra/if_netlink.c | 148 |
1 files changed, 111 insertions, 37 deletions
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index a15f932451..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; } @@ -721,10 +798,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (tb[IFLA_LINK]) link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - if (tb[IFLA_LINK_NETNSID]) { + if (tb[IFLA_LINK_NETNSID]) link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]); - link_nsid = ns_id_get_absolute(ns_id, link_nsid); - } /* Add interface. * We add by index first because in some cases such as the master @@ -732,9 +807,11 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) * back references on the slave interfaces is painful if not done * this way, i.e. by creating by ifindex. */ - ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id, name); + ifp = if_get_by_ifindex(ifi->ifi_index, vrf_id); set_ifindex(ifp, ifi->ifi_index, zns); /* add it to ns struct */ + if_set_name(ifp, name); + ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]); ifp->metric = 0; @@ -771,7 +848,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup) netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1, link_nsid); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) - zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id); + zebra_l2if_update_bridge_slave(ifp, bridge_ifindex); else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) zebra_l2if_update_bond_slave(ifp, bond_ifindex); @@ -1263,10 +1340,9 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) if (tb[IFLA_LINK]) link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]); - if (tb[IFLA_LINK_NETNSID]) { + if (tb[IFLA_LINK_NETNSID]) link_nsid = *(ns_id_t *)RTA_DATA(tb[IFLA_LINK_NETNSID]); - link_nsid = ns_id_get_absolute(ns_id, link_nsid); - } + if (tb[IFLA_IFALIAS]) { desc = (char *)RTA_DATA(tb[IFLA_IFALIAS]); } @@ -1354,8 +1430,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) 1, link_nsid); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) zebra_l2if_update_bridge_slave(ifp, - bridge_ifindex, - ns_id); + bridge_ifindex); else if (IS_ZEBRA_IF_BOND_SLAVE(ifp)) zebra_l2if_update_bond_slave(ifp, bond_ifindex); } else if (ifp->vrf_id != vrf_id) { @@ -1456,8 +1531,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup) 0, link_nsid); if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave) zebra_l2if_update_bridge_slave(ifp, - bridge_ifindex, - ns_id); + bridge_ifindex); else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave) zebra_l2if_update_bond_slave(ifp, bond_ifindex); } |
