system-linux: improve handling of device rename
[project/netifd.git] / system-linux.c
index 775b448e56f17e35c106cb37a2a76ee0b0dc8623..3b09bbb8453080d769ca3fde4db59bfaa63866c1 100644 (file)
@@ -74,6 +74,7 @@
 #include "netifd.h"
 #include "device.h"
 #include "system.h"
+#include "utils.h"
 
 struct event_socket {
        struct uloop_fd uloop;
@@ -591,6 +592,9 @@ static int cb_rtnl_event(struct nl_msg *msg, void *arg)
        if (!system_get_dev_sysctl("/sys/class/net/%s/carrier", dev->ifname, buf, sizeof(buf)))
                link_state = strtoul(buf, NULL, 0);
 
+       if (dev->type == &simple_device_type && !system_if_force_external(dev->ifname))
+               device_set_present(dev, true);
+
        device_set_link(dev, link_state ? true : false);
 
 out:
@@ -653,13 +657,15 @@ handle_hotplug_msg(char *data, int size)
 move:
        dev = device_find(interface_old);
        if (!dev)
-               goto found;
+               return;
 
        if (dev->type != &simple_device_type)
                goto found;
 
        device_set_present(dev, false);
 
+       return;
+
 found:
        dev = device_find(interface);
        if (!dev)
@@ -1246,21 +1252,26 @@ nla_put_failure:
        return -ENOMEM;
 }
 
-int system_link_netns_move(const char *ifname, int netns_fd)
+int system_link_netns_move(struct device *dev, int netns_fd, const char *target_ifname)
 {
        struct nl_msg *msg;
        struct ifinfomsg iim = {
                .ifi_family = AF_UNSPEC,
-               .ifi_index = 0,
        };
 
+       if (!dev)
+               return -1;
+
+       iim.ifi_index = system_if_resolve(dev);
        msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST);
 
        if (!msg)
                return -1;
 
        nlmsg_append(msg, &iim, sizeof(iim), 0);
-       nla_put_string(msg, IFLA_IFNAME, ifname);
+       if (target_ifname)
+               nla_put_string(msg, IFLA_IFNAME, target_ifname);
+
        nla_put_u32(msg, IFLA_NET_NS_FD, netns_fd);
        return system_rtnl_call(msg);
 }
@@ -1396,8 +1407,10 @@ int system_vlan_del(struct device *dev)
 int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlandev_config *cfg)
 {
        struct nl_msg *msg;
-       struct nlattr *linkinfo, *data;
+       struct nlattr *linkinfo, *data, *qos;
        struct ifinfomsg iim = { .ifi_family = AF_UNSPEC };
+       struct vlan_qos_mapping *elem;
+       struct ifla_vlan_qos_mapping nl_qos_map;
        int rv;
 
        msg = nlmsg_alloc_simple(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
@@ -1426,6 +1439,26 @@ int system_vlandev_add(struct device *vlandev, struct device *dev, struct vlande
                netifd_log_message(L_WARNING, "%s Your kernel is older than linux 3.10.0, 802.1ad is not supported defaulting to 802.1q", vlandev->type->name);
 #endif
 
+       if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
+               goto nla_put_failure;
+
+       vlist_simple_for_each_element(&cfg->ingress_qos_mapping_list, elem, node) {
+               nl_qos_map.from = elem->from;
+               nl_qos_map.to = elem->to;
+               nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
+       }
+       nla_nest_end(msg, qos);
+
+       if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
+               goto nla_put_failure;
+
+       vlist_simple_for_each_element(&cfg->egress_qos_mapping_list, elem, node) {
+               nl_qos_map.from = elem->from;
+               nl_qos_map.to = elem->to;
+               nla_put(msg, IFLA_VLAN_QOS_MAPPING, sizeof(nl_qos_map), &nl_qos_map);
+       }
+       nla_nest_end(msg, qos);
+
        nla_nest_end(msg, data);
        nla_nest_end(msg, linkinfo);