]> git.proxmox.com Git - mirror_lxc.git/commitdiff
network: rework network device creation
authorChristian Brauner <christian.brauner@ubuntu.com>
Fri, 10 Jan 2020 11:30:02 +0000 (12:30 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Fri, 10 Jan 2020 11:36:47 +0000 (12:36 +0100)
This makes all the codepaths easier to follow and also moves and renames
devices in one single step.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/network.c

index 5618caea856d25cb4e197b493bd60df0db30310f..c8f44dd807a759551590109f54230f3bdf6948be 100644 (file)
@@ -47,6 +47,7 @@
 lxc_log_define(network, lxc);
 
 typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
+typedef int (*instantiate_ns_cb)(struct lxc_netdev *);
 static const char loop_device[] = "lo";
 
 static int lxc_ip_route_dest(__u16 nlmsg_type, int family, int ifindex, void *dest, unsigned int netmask)
@@ -501,6 +502,8 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
        }
 
        strlcpy(netdev->created_name, peer, IFNAMSIZ);
+       if (netdev->name[0] == '\0')
+               (void)strlcpy(netdev->name, peer, IFNAMSIZ);
 
        netdev->ifindex = if_nametoindex(peer);
        if (!netdev->ifindex) {
@@ -663,6 +666,8 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
        }
 
        strlcpy(netdev->created_name, peer, IFNAMSIZ);
+       if (netdev->name[0] == '\0')
+               (void)strlcpy(netdev->name, peer, IFNAMSIZ);
 
        netdev->ifindex = if_nametoindex(peer);
        if (!netdev->ifindex) {
@@ -736,6 +741,8 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
        }
 
        strlcpy(netdev->created_name, peer, IFNAMSIZ);
+       if (netdev->name[0] == '\0')
+               (void)strlcpy(netdev->name, peer, IFNAMSIZ);
 
        netdev->ifindex = if_nametoindex(peer);
        if (!netdev->ifindex) {
@@ -809,6 +816,8 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
        }
 
        strlcpy(netdev->created_name, netdev->link, IFNAMSIZ);
+       if (netdev->name[0] == '\0')
+               (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
 
        /*
         * Store the ifindex of the host's network device in the host's
@@ -903,6 +912,102 @@ static  instantiate_cb netdev_conf[LXC_NET_MAXCONFTYPE + 1] = {
        [LXC_NET_NONE]    = instantiate_none,
 };
 
+static int instantiate_ns_veth(struct lxc_netdev *netdev)
+{
+       char current_ifname[IFNAMSIZ];
+
+       netdev->ifindex = if_nametoindex(netdev->created_name);
+       if (!netdev->ifindex)
+               return log_error_errno(-1,
+                                      errno, "Failed to retrieve ifindex for network device with name %s",
+                                      netdev->created_name);
+
+       if (netdev->name[0] == '\0')
+               (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
+
+       if (strcmp(netdev->created_name, netdev->name) != 0) {
+               int ret;
+
+               ret = lxc_netdev_rename_by_name(netdev->created_name, netdev->name);
+               if (ret)
+                       return log_error_errno(-1,
+                                              -ret, "Failed to rename network device \"%s\" to \"%s\"",
+                                              netdev->created_name,
+                                              netdev->name);
+
+               TRACE("Renamed network device from \"%s\" to \"%s\"", netdev->created_name, netdev->name);
+       }
+
+       /*
+        * Re-read the name of the interface because its name has changed and
+        * would be automatically allocated by the system
+        */
+       if (!if_indextoname(netdev->ifindex, current_ifname))
+               return log_error_errno(-1,
+                                      errno, "Failed get name for network device with ifindex %d",
+                                      netdev->ifindex);
+
+       /*
+        * Now update the recorded name of the network device to reflect the
+        * name of the network device in the child's network namespace. We will
+        * later on send this information back to the parent.
+        */
+       (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
+
+       return 0;
+}
+
+static int __instantiate_common(struct lxc_netdev *netdev)
+{
+       netdev->ifindex = if_nametoindex(netdev->name);
+       if (!netdev->ifindex)
+               return log_error_errno(-1,
+                                      errno, "Failed to retrieve ifindex for network device with name %s",
+                                      netdev->name);
+
+       return 0;
+}
+
+static int instantiate_ns_macvlan(struct lxc_netdev *netdev)
+{
+       return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_ipvlan(struct lxc_netdev *netdev)
+{
+       return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_vlan(struct lxc_netdev *netdev)
+{
+       return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_phys(struct lxc_netdev *netdev)
+{
+       return __instantiate_common(netdev);
+}
+
+static int instantiate_ns_empty(struct lxc_netdev *netdev)
+{
+       return 0;
+}
+
+static int instantiate_ns_none(struct lxc_netdev *netdev)
+{
+       return 0;
+}
+
+static  instantiate_ns_cb netdev_ns_conf[LXC_NET_MAXCONFTYPE + 1] = {
+       [LXC_NET_VETH]    = instantiate_ns_veth,
+       [LXC_NET_MACVLAN] = instantiate_ns_macvlan,
+       [LXC_NET_IPVLAN]  = instantiate_ns_ipvlan,
+       [LXC_NET_VLAN]    = instantiate_ns_vlan,
+       [LXC_NET_PHYS]    = instantiate_ns_phys,
+       [LXC_NET_EMPTY]   = instantiate_ns_empty,
+       [LXC_NET_NONE]    = instantiate_ns_none,
+};
+
 static int shutdown_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        int ret;
@@ -3249,7 +3354,7 @@ int lxc_network_move_created_netdev_priv(struct lxc_handler *handler)
                if (physname)
                        ret = lxc_netdev_move_wlan(physname, netdev->link, pid, NULL);
                else
-                       ret = lxc_netdev_move_by_index(netdev->ifindex, pid, NULL);
+                       ret = lxc_netdev_move_by_index(netdev->ifindex, pid, netdev->name);
                if (ret) {
                        errno = -ret;
                        SYSERROR("Failed to move network device \"%s\" with ifindex %d to network namespace %d",
@@ -3585,98 +3690,26 @@ static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
        return 0;
 }
 
-static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
+static int lxc_network_setup_in_child_namespaces_common(struct lxc_netdev *netdev)
 {
-       char ifname[IFNAMSIZ];
        int err;
-       char *current_ifname = ifname;
        char bufinet4[INET_ADDRSTRLEN], bufinet6[INET6_ADDRSTRLEN];
 
        /* empty network namespace */
-       if (!netdev->ifindex) {
-               if (netdev->flags & IFF_UP) {
-                       err = lxc_netdev_up("lo");
-                       if (err) {
-                               errno = -err;
-                               SYSERROR("Failed to set the loopback network device up");
-                               return -1;
-                       }
-               }
-
-               if (netdev->type == LXC_NET_EMPTY)
-                       return 0;
-
-               if (netdev->type == LXC_NET_NONE)
-                       return 0;
-
-               netdev->ifindex = if_nametoindex(netdev->created_name);
-               if (!netdev->ifindex)
-                       SYSERROR("Failed to retrieve ifindex for network device with name %s",
-                                netdev->created_name ?: "(null)");
-       }
-
-       /* get the new ifindex in case of physical netdev */
-       if (netdev->type == LXC_NET_PHYS) {
-               netdev->ifindex = if_nametoindex(netdev->link);
-               if (!netdev->ifindex) {
-                       ERROR("Failed to get ifindex for network device \"%s\"",
-                             netdev->link);
-                       return -1;
-               }
-       }
-
-       /* retrieve the name of the interface */
-       if (!if_indextoname(netdev->ifindex, current_ifname)) {
-               SYSERROR("Failed to retrieve name for network device with ifindex %d",
-                        netdev->ifindex);
-               return -1;
-       }
-
-       /* Default: let the system choose an interface name.
-        * When the IFLA_IFNAME attribute is passed something like "<prefix>%d"
-        * netlink will replace the format specifier with an appropriate index.
-        */
-       if (netdev->name[0] == '\0') {
-               if (netdev->type == LXC_NET_PHYS)
-                       (void)strlcpy(netdev->name, netdev->link, IFNAMSIZ);
-               else
-                       (void)strlcpy(netdev->name, "eth%d", IFNAMSIZ);
-       }
-
-       /* rename the interface name */
-       if (strcmp(current_ifname, netdev->name) != 0) {
-               err = lxc_netdev_rename_by_name(current_ifname, netdev->name);
+       if (!netdev->ifindex && netdev->flags & IFF_UP) {
+               err = lxc_netdev_up("lo");
                if (err) {
                        errno = -err;
-                       SYSERROR("Failed to rename network device \"%s\" to \"%s\"",
-                                current_ifname, netdev->name);
+                       SYSERROR( "Failed to set the loopback network device up");
                        return -1;
                }
-
-               TRACE("Renamed network device from \"%s\" to \"%s\"",
-                     current_ifname, netdev->name);
-       }
-
-       /* Re-read the name of the interface because its name has changed
-        * and would be automatically allocated by the system
-        */
-       if (!if_indextoname(netdev->ifindex, current_ifname)) {
-               ERROR("Failed get name for network device with ifindex %d",
-                     netdev->ifindex);
-               return -1;
        }
 
-       /* Now update the recorded name of the network device to reflect the
-        * name of the network device in the child's network namespace. We will
-        * later on send this information back to the parent.
-        */
-       (void)strlcpy(netdev->name, current_ifname, IFNAMSIZ);
-
        /* set a mac address */
        if (netdev->hwaddr) {
-               if (setup_hw_addr(netdev->hwaddr, current_ifname)) {
+               if (setup_hw_addr(netdev->hwaddr, netdev->name)) {
                        ERROR("Failed to setup hw address for network device \"%s\"",
-                             current_ifname);
+                             netdev->name);
                        return -1;
                }
        }
@@ -3684,24 +3717,24 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
        /* setup ipv4 addresses on the interface */
        if (setup_ipv4_addr(&netdev->ipv4, netdev->ifindex)) {
                ERROR("Failed to setup ip addresses for network device \"%s\"",
-                     current_ifname);
+                     netdev->name);
                return -1;
        }
 
        /* setup ipv6 addresses on the interface */
        if (setup_ipv6_addr(&netdev->ipv6, netdev->ifindex)) {
                ERROR("Failed to setup ipv6 addresses for network device \"%s\"",
-                     current_ifname);
+                     netdev->name);
                return -1;
        }
 
        /* set the network device up */
        if (netdev->flags & IFF_UP) {
-               err = lxc_netdev_up(current_ifname);
+               err = lxc_netdev_up(netdev->name);
                if (err) {
                        errno = -err;
                        SYSERROR("Failed to set network device \"%s\" up",
-                                current_ifname);
+                                netdev->name);
                        return -1;
                }
 
@@ -3718,13 +3751,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
        if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) {
                if (!(netdev->flags & IFF_UP)) {
                        ERROR("Cannot add ipv4 gateway for network device "
-                             "\"%s\" when not bringing up the interface", current_ifname);
+                             "\"%s\" when not bringing up the interface", netdev->name);
                        return -1;
                }
 
                if (lxc_list_empty(&netdev->ipv4)) {
                        ERROR("Cannot add ipv4 gateway for network device "
-                             "\"%s\" when not assigning an address", current_ifname);
+                             "\"%s\" when not assigning an address", netdev->name);
                        return -1;
                }
 
@@ -3733,7 +3766,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                        err = lxc_ipv4_gateway_add(netdev->ifindex, NULL);
                        if (err < 0) {
                                SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
-                                        current_ifname);
+                                        netdev->name);
                                return ret_set_errno(-1, -err);
                        }
                } else {
@@ -3753,7 +3786,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                                if (err < 0) {
                                        errno = -err;
                                        SYSERROR("Failed to add ipv4 dest \"%s\" for network device \"%s\"",
-                                               bufinet4, current_ifname);
+                                               bufinet4, netdev->name);
                                        return -1;
                                }
 
@@ -3761,7 +3794,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                                if (err < 0) {
                                        errno = -err;
                                        SYSERROR("Failed to setup ipv4 gateway \"%s\" for network device \"%s\"",
-                                               bufinet4, current_ifname);
+                                               bufinet4, netdev->name);
                                        return -1;
                                }
                        }
@@ -3772,13 +3805,13 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
        if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) {
                if (!(netdev->flags & IFF_UP)) {
                        ERROR("Cannot add ipv6 gateway for network device \"%s\" when not bringing up the interface",
-                             current_ifname);
+                             netdev->name);
                        return -1;
                }
 
                if (lxc_list_empty(&netdev->ipv6) && !IN6_IS_ADDR_LINKLOCAL(netdev->ipv6_gateway)) {
                        ERROR("Cannot add ipv6 gateway for network device \"%s\" when not assigning an address",
-                             current_ifname);
+                             netdev->name);
                        return -1;
                }
 
@@ -3787,7 +3820,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                        err = lxc_ipv6_gateway_add(netdev->ifindex, NULL);
                        if (err < 0) {
                                SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
-                                        current_ifname);
+                                        netdev->name);
                                return ret_set_errno(-1, -err);
                        }
                } else {
@@ -3807,7 +3840,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                                if (err < 0) {
                                        errno = -err;
                                        SYSERROR("Failed to add ipv6 dest \"%s\" for network device \"%s\"",
-                                               bufinet6, current_ifname);
+                                               bufinet6, netdev->name);
                                        return -1;
                                }
 
@@ -3815,14 +3848,14 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
                                if (err < 0) {
                                        errno = -err;
                                        SYSERROR("Failed to setup ipv6 gateway \"%s\" for network device \"%s\"",
-                                               bufinet6, current_ifname);
+                                               bufinet6, netdev->name);
                                        return -1;
                                }
                        }
                }
        }
 
-       DEBUG("Network device \"%s\" has been setup", current_ifname);
+       DEBUG("Network device \"%s\" has been setup", netdev->name);
 
        return 0;
 }
@@ -3832,10 +3865,14 @@ int lxc_setup_network_in_child_namespaces(const struct lxc_conf *conf,
 {
        struct lxc_list *iterator;
 
-       lxc_list_for_each(iterator, network) {
+       lxc_list_for_each (iterator, network) {
                struct lxc_netdev *netdev = iterator->elem;
+               int ret;
 
-               if (lxc_setup_netdev_in_child_namespaces(netdev)) {
+               ret = netdev_ns_conf[netdev->type](netdev);
+               if (!ret)
+                       ret = lxc_network_setup_in_child_namespaces_common(netdev);
+               if (ret) {
                        ERROR("Failed to setup netdev");
                        return -1;
                }