]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/if_netlink.c
zebra, lib: fix the ZEBRA_INTERFACE_VRF_UPDATE zapi message
[mirror_frr.git] / zebra / if_netlink.c
index 47a101e619b84055c193934d7570879b219de141..f4bd193569b89444173a5f14e1248324f0d7ee7a 100644 (file)
@@ -243,7 +243,8 @@ static enum zebra_link_type netlink_to_zebra_link_type(unsigned int hwt)
        }
 }
 
-static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
+static void netlink_determine_zebra_iftype(const char *kind,
+                                          zebra_iftype_t *zif_type)
 {
        *zif_type = ZEBRA_IF_OTHER;
 
@@ -262,6 +263,10 @@ static void netlink_determine_zebra_iftype(char *kind, zebra_iftype_t *zif_type)
                *zif_type = ZEBRA_IF_MACVLAN;
        else if (strcmp(kind, "veth") == 0)
                *zif_type = ZEBRA_IF_VETH;
+       else if (strcmp(kind, "bond") == 0)
+               *zif_type = ZEBRA_IF_BOND;
+       else if (strcmp(kind, "bond_slave") == 0)
+               *zif_type = ZEBRA_IF_BOND_SLAVE;
 }
 
 #define parse_rtattr_nested(tb, max, rta)                                      \
@@ -585,6 +590,8 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
        ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
        ifindex_t link_ifindex = IFINDEX_INTERNAL;
+       ifindex_t bond_ifindex = IFINDEX_INTERNAL;
+       struct zebra_if *zif;
 
        zns = zebra_ns_lookup(ns_id);
        ifi = NLMSG_DATA(h);
@@ -634,7 +641,10 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                if (linkinfo[IFLA_INFO_SLAVE_KIND])
                        slave_kind = RTA_DATA(linkinfo[IFLA_INFO_SLAVE_KIND]);
 
-               netlink_determine_zebra_iftype(kind, &zif_type);
+               if ((slave_kind != NULL) && strcmp(slave_kind, "bond") == 0)
+                       netlink_determine_zebra_iftype("bond_slave", &zif_type);
+               else
+                       netlink_determine_zebra_iftype(kind, &zif_type);
        }
 
        /* If VRF, create the VRF structure itself. */
@@ -652,6 +662,9 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                        zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
                        bridge_ifindex =
                                *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+               } else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
+                       zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+                       bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
                } else
                        zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
        }
@@ -663,7 +676,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                link_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_LINK]);
 
        /* Add interface. */
-       ifp = if_get_by_name(name, vrf_id, 0);
+       ifp = if_get_by_name(name, vrf_id);
        set_ifindex(ifp, ifi->ifi_index, zns);
        ifp->flags = ifi->ifi_flags & 0x0000fffff;
        ifp->mtu6 = ifp->mtu = *(uint32_t *)RTA_DATA(tb[IFLA_MTU]);
@@ -679,8 +692,14 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        if (IS_ZEBRA_IF_VRF(ifp))
                SET_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK);
 
-       /* Update link. */
-       zebra_if_update_link(ifp, link_ifindex, ns_id);
+       /*
+        * Just set the @link/lower-device ifindex. During nldump interfaces are
+        * not ordered in any fashion so we may end up getting upper devices
+        * before lower devices. We will setup the real linkage once the dump
+        * is complete.
+        */
+       zif = (struct zebra_if *)ifp->info;
+       zif->link_ifindex = link_ifindex;
 
        /* Hardware type and address. */
        ifp->ll_type = netlink_to_zebra_link_type(ifi->ifi_type);
@@ -693,13 +712,15 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        netlink_interface_update_l2info(ifp, linkinfo[IFLA_INFO_DATA], 1);
        if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
                zebra_l2if_update_bridge_slave(ifp, bridge_ifindex);
+       else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+               zebra_l2if_update_bond_slave(ifp, bond_ifindex);
 
        return 0;
 }
 
 /* Request for specific interface or address information from the kernel */
-static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type,
-                                    uint32_t filter_mask)
+static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
+                                    int type, uint32_t filter_mask)
 {
        struct {
                struct nlmsghdr n;
@@ -717,57 +738,65 @@ static int netlink_request_intf_addr(struct zebra_ns *zns, int family, int type,
        if (filter_mask)
                addattr32(&req.n, sizeof(req), IFLA_EXT_MASK, filter_mask);
 
-       return netlink_request(&zns->netlink_cmd, &req.n);
+       return netlink_request(netlink_cmd, &req.n);
 }
 
 /* Interface lookup by netlink socket. */
 int interface_lookup_netlink(struct zebra_ns *zns)
 {
        int ret;
+       struct zebra_dplane_info dp_info;
+       struct nlsock *netlink_cmd = &zns->netlink_cmd;
+
+       /* Capture key info from ns struct */
+       zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
 
        /* Get interface information. */
-       ret = netlink_request_intf_addr(zns, AF_PACKET, RTM_GETLINK, 0);
+       ret = netlink_request_intf_addr(netlink_cmd, AF_PACKET, RTM_GETLINK, 0);
        if (ret < 0)
                return ret;
-       ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
+       ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
                                 1);
        if (ret < 0)
                return ret;
 
        /* Get interface information - for bridge interfaces. */
-       ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK,
+       ret = netlink_request_intf_addr(netlink_cmd, AF_BRIDGE, RTM_GETLINK,
                                        RTEXT_FILTER_BRVLAN);
        if (ret < 0)
                return ret;
-       ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
+       ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
                                 0);
        if (ret < 0)
                return ret;
 
        /* Get interface information - for bridge interfaces. */
-       ret = netlink_request_intf_addr(zns, AF_BRIDGE, RTM_GETLINK,
+       ret = netlink_request_intf_addr(netlink_cmd, AF_BRIDGE, RTM_GETLINK,
                                        RTEXT_FILTER_BRVLAN);
        if (ret < 0)
                return ret;
-       ret = netlink_parse_info(netlink_interface, &zns->netlink_cmd, zns, 0,
+       ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
                                 0);
        if (ret < 0)
                return ret;
 
+       /* fixup linkages */
+       zebra_if_update_all_links();
+
        /* Get IPv4 address of the interfaces. */
-       ret = netlink_request_intf_addr(zns, AF_INET, RTM_GETADDR, 0);
+       ret = netlink_request_intf_addr(netlink_cmd, AF_INET, RTM_GETADDR, 0);
        if (ret < 0)
                return ret;
-       ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns,
+       ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
                                 0, 1);
        if (ret < 0)
                return ret;
 
        /* Get IPv6 address of the interfaces. */
-       ret = netlink_request_intf_addr(zns, AF_INET6, RTM_GETADDR, 0);
+       ret = netlink_request_intf_addr(netlink_cmd, AF_INET6, RTM_GETADDR, 0);
        if (ret < 0)
                return ret;
-       ret = netlink_parse_info(netlink_interface_addr, &zns->netlink_cmd, zns,
+       ret = netlink_parse_info(netlink_interface_addr, netlink_cmd, &dp_info,
                                 0, 1);
        if (ret < 0)
                return ret;
@@ -1066,6 +1095,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
        zebra_iftype_t zif_type = ZEBRA_IF_OTHER;
        zebra_slave_iftype_t zif_slave_type = ZEBRA_IF_SLAVE_NONE;
        ifindex_t bridge_ifindex = IFINDEX_INTERNAL;
+       ifindex_t bond_ifindex = IFINDEX_INTERNAL;
        ifindex_t link_ifindex = IFINDEX_INTERNAL;
 
 
@@ -1165,6 +1195,11 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                                zif_slave_type = ZEBRA_IF_SLAVE_BRIDGE;
                                bridge_ifindex =
                                        *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+                       } else if (slave_kind
+                                  && (strcmp(slave_kind, "bond") == 0)) {
+                               zif_slave_type = ZEBRA_IF_SLAVE_BOND;
+                               bond_ifindex =
+                                       *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
                        } else
                                zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
                }
@@ -1183,7 +1218,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
                        if (ifp == NULL) {
                                /* unknown interface */
-                               ifp = if_get_by_name(name, vrf_id, 0);
+                               ifp = if_get_by_name(name, vrf_id);
                        } else {
                                /* pre-configured interface, learnt now */
                                if (ifp->vrf_id != vrf_id)
@@ -1224,6 +1259,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                        if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
                                zebra_l2if_update_bridge_slave(ifp,
                                                               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) {
                        /* VRF change for an interface. */
                        if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1235,7 +1272,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
                        if_handle_vrf_change(ifp, vrf_id);
                } else {
-                       int was_bridge_slave;
+                       bool was_bridge_slave, was_bond_slave;
 
                        /* Interface update. */
                        if (IS_ZEBRA_DEBUG_KERNEL)
@@ -1258,6 +1295,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                        /* Update interface type - NOTE: Only slave_type can
                         * change. */
                        was_bridge_slave = IS_ZEBRA_IF_BRIDGE_SLAVE(ifp);
+                       was_bond_slave = IS_ZEBRA_IF_BOND_SLAVE(ifp);
                        zebra_if_set_ziftype(ifp, zif_type, zif_slave_type);
 
                        netlink_interface_update_hw_addr(tb, ifp);
@@ -1297,6 +1335,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
                        if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp) || was_bridge_slave)
                                zebra_l2if_update_bridge_slave(ifp,
                                                               bridge_ifindex);
+                       else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
+                               zebra_l2if_update_bond_slave(ifp, bond_ifindex);
                }
        } else {
                /* Delete interface notification from kernel */