]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
network: improve veth device creation
authorChristian Brauner <christian.brauner@ubuntu.com>
Thu, 9 Jan 2020 11:29:22 +0000 (12:29 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 9 Jan 2020 15:54:48 +0000 (16:54 +0100)
This allows us to avoid having to move the network device. It also allows us to
work around a kernel bug that in combination with a recent change in systemd
244 causes uses of systemd-networkd to not get an ip address.

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

index cfb9d8d563c2b3693a3f42d611add4123d84c3cb..43b58d11ce6e0c31e82605b3c1a635cd738925e8 100644 (file)
@@ -487,11 +487,11 @@ static char *find_line(char *buf_start, char *buf_end, char *name,
        return NULL;
 }
 
-static int instantiate_veth(char *veth1, char *veth2)
+static int instantiate_veth(char *veth1, char *veth2, pid_t pid, unsigned int mtu)
 {
        int ret;
 
-       ret = lxc_veth_create(veth1, veth2);
+       ret = lxc_veth_create(veth1, veth2, pid, mtu);
        if (ret < 0) {
                errno = -ret;
                CMD_SYSERROR("Failed to create %s-%s\n", veth1, veth2);
@@ -524,8 +524,9 @@ static int get_mtu(char *name)
 
 static int create_nic(char *nic, char *br, int pid, char **cnic)
 {
+       unsigned int mtu = 1500;
+       int ret;
        char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ];
-       int mtu, ret;
 
        ret = snprintf(veth1buf, IFNAMSIZ, "%s", nic);
        if (ret < 0 || ret >= IFNAMSIZ) {
@@ -539,16 +540,19 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
                return -1;
        }
 
+       if (strcmp(br, "none"))
+               mtu = get_mtu(br);
+       if (!mtu)
+               mtu = 1500;
+
        /* create the nics */
-       ret = instantiate_veth(veth1buf, veth2buf);
+       ret = instantiate_veth(veth1buf, veth2buf, pid, mtu);
        if (ret < 0) {
                usernic_error("%s", "Error creating veth tunnel\n");
                return -1;
        }
 
        if (strcmp(br, "none")) {
-               /* copy the bridge's mtu to both ends */
-               mtu = get_mtu(br);
                if (mtu > 0) {
                        ret = lxc_netdev_set_mtu(veth1buf, mtu);
                        if (ret < 0) {
@@ -556,13 +560,6 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
                                              mtu, veth1buf);
                                goto out_del;
                        }
-
-                       ret = lxc_netdev_set_mtu(veth2buf, mtu);
-                       if (ret < 0) {
-                               usernic_error("Failed to set mtu to %d on %s\n",
-                                             mtu, veth2buf);
-                               goto out_del;
-                       }
                }
 
                /* attach veth1 to bridge */
@@ -573,14 +570,6 @@ static int create_nic(char *nic, char *br, int pid, char **cnic)
                }
        }
 
-       /* pass veth2 to target netns */
-       ret = lxc_netdev_move_by_name(veth2buf, pid, NULL);
-       if (ret < 0) {
-               usernic_error("Error moving %s to network namespace of %d\n",
-                             veth2buf, pid);
-               goto out_del;
-       }
-
        *cnic = strdup(veth2buf);
        if (!*cnic) {
                usernic_error("Failed to copy string \"%s\"\n", veth2buf);
index 65eca60e832a4e5fb0a234e0855517286236ec16..25a35093ce13549da5380a686b8929f51a6f8d15 100644 (file)
@@ -271,10 +271,10 @@ static int lxc_is_ip_forwarding_enabled(const char *ifname, int family)
 
 static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
-       int bridge_index, err;
+       int err;
+       unsigned int mtu;
        char *veth1, *veth2;
        char veth1buf[IFNAMSIZ], veth2buf[IFNAMSIZ];
-       unsigned int mtu = 0;
 
        if (netdev->priv.veth_attr.pair[0] != '\0') {
                veth1 = netdev->priv.veth_attr.pair;
@@ -299,13 +299,25 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
 
        veth2 = lxc_mkifname(veth2buf);
        if (!veth2)
-               goto out_delete;
+               return -1;
+
+       if (netdev->mtu && lxc_safe_uint(netdev->mtu, &mtu)) {
+               return log_error_errno(-1, errno, "Failed to parse mtu");
+       } else if (netdev->link[0] != '\0') {
+               int ifindex_mtu;
 
-       err = lxc_veth_create(veth1, veth2);
+               ifindex_mtu = if_nametoindex(netdev->link);
+               if (ifindex_mtu) {
+                       mtu = netdev_get_mtu(ifindex_mtu);
+                       INFO("Retrieved mtu %d from %s", mtu, netdev->link);
+               }
+       }
+
+       err = lxc_veth_create(veth1, veth2, handler->pid, mtu);
        if (err) {
                errno = -err;
                SYSERROR("Failed to create veth pair \"%s\" and \"%s\"", veth1, veth2);
-               goto out_delete;
+               return -1;
        }
 
        strlcpy(netdev->created_name, veth2, IFNAMSIZ);
@@ -327,42 +339,11 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
                goto out_delete;
        }
 
-       /* Note that we're retrieving the container's ifindex in the host's
-        * network namespace because we need it to move the device from the
-        * host's network namespace to the container's network namespace later
-        * on.
-        */
-       netdev->ifindex = if_nametoindex(veth2);
-       if (!netdev->ifindex) {
-               ERROR("Failed to retrieve ifindex for \"%s\"", veth2);
-               goto out_delete;
-       }
-
-       if (netdev->mtu) {
-               if (lxc_safe_uint(netdev->mtu, &mtu) < 0)
-                       WARN("Failed to parse mtu");
-               else
-                       INFO("Retrieved mtu %d", mtu);
-       } else if (netdev->link[0] != '\0') {
-               bridge_index = if_nametoindex(netdev->link);
-               if (bridge_index) {
-                       mtu = netdev_get_mtu(bridge_index);
-                       INFO("Retrieved mtu %d from %s", mtu, netdev->link);
-               } else {
-                       mtu = netdev_get_mtu(netdev->ifindex);
-                       INFO("Retrieved mtu %d from %s", mtu, veth2);
-               }
-       }
-
        if (mtu) {
                err = lxc_netdev_set_mtu(veth1, mtu);
-               if (!err)
-                       err = lxc_netdev_set_mtu(veth2, mtu);
-
                if (err) {
                        errno = -err;
-                       SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" "
-                                "and \"%s\"", mtu, veth1, veth2);
+                       SYSERROR("Failed to set mtu \"%d\" for veth pair \"%s\" ", mtu, veth1);
                        goto out_delete;
                }
        }
@@ -484,14 +465,12 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
                        goto out_delete;
        }
 
-       DEBUG("Instantiated veth \"%s/%s\", index is \"%d\"", veth1, veth2,
-             netdev->ifindex);
+       DEBUG("Instantiated veth tunnel \"%s <--> %s\"", veth1, veth2);
 
        return 0;
 
 out_delete:
-       if (netdev->ifindex != 0)
-               lxc_netdev_delete_by_name(veth1);
+       lxc_netdev_delete_by_name(veth1);
        return -1;
 }
 
@@ -499,7 +478,6 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
 {
        char peer[IFNAMSIZ];
        int err;
-       unsigned int mtu = 0;
 
        if (netdev->link[0] == '\0') {
                ERROR("No link for macvlan network device specified");
@@ -531,6 +509,8 @@ static int instantiate_macvlan(struct lxc_handler *handler, struct lxc_netdev *n
        }
 
        if (netdev->mtu) {
+               unsigned int mtu;
+
                err = lxc_safe_uint(netdev->mtu, &mtu);
                if (err < 0) {
                        errno = -err;
@@ -661,7 +641,6 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
 {
        char peer[IFNAMSIZ];
        int err;
-       unsigned int mtu = 0;
 
        if (netdev->link[0] == '\0') {
                ERROR("No link for ipvlan network device specified");
@@ -692,19 +671,19 @@ static int instantiate_ipvlan(struct lxc_handler *handler, struct lxc_netdev *ne
        }
 
        if (netdev->mtu) {
+               unsigned int mtu;
+
                err = lxc_safe_uint(netdev->mtu, &mtu);
                if (err < 0) {
                        errno = -err;
-                       SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"",
-                                netdev->mtu, peer);
+                       SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
                        goto on_error;
                }
 
                err = lxc_netdev_set_mtu(peer, mtu);
                if (err < 0) {
                        errno = -err;
-                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"",
-                                netdev->mtu, peer);
+                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
                        goto on_error;
                }
        }
@@ -737,7 +716,6 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
        char peer[IFNAMSIZ];
        int err;
        static uint16_t vlan_cntr = 0;
-       unsigned int mtu = 0;
 
        if (netdev->link[0] == '\0') {
                ERROR("No link for vlan network device specified");
@@ -766,19 +744,19 @@ static int instantiate_vlan(struct lxc_handler *handler, struct lxc_netdev *netd
        }
 
        if (netdev->mtu) {
+               unsigned int mtu;
+
                err = lxc_safe_uint(netdev->mtu, &mtu);
                if (err < 0) {
                        errno = -err;
-                       SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"",
-                                netdev->mtu, peer);
+                       SYSERROR("Failed to parse mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
                        goto on_error;
                }
 
                err = lxc_netdev_set_mtu(peer, mtu);
-               if (err) {
+               if (err < 0) {
                        errno = -err;
-                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"",
-                                netdev->mtu, peer);
+                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, peer);
                        goto on_error;
                }
        }
@@ -810,7 +788,6 @@ on_error:
 static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netdev)
 {
        int err, mtu_orig = 0;
-       unsigned int mtu = 0;
 
        if (netdev->link[0] == '\0') {
                ERROR("No link for physical interface specified");
@@ -852,6 +829,8 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
        netdev->priv.phys_attr.mtu = mtu_orig;
 
        if (netdev->mtu) {
+               unsigned int mtu;
+
                err = lxc_safe_uint(netdev->mtu, &mtu);
                if (err < 0) {
                        errno = -err;
@@ -863,8 +842,7 @@ static int instantiate_phys(struct lxc_handler *handler, struct lxc_netdev *netd
                err = lxc_netdev_set_mtu(netdev->link, mtu);
                if (err < 0) {
                        errno = -err;
-                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"",
-                                netdev->mtu, netdev->link);
+                       SYSERROR("Failed to set mtu \"%s\" for interface \"%s\"", netdev->mtu, netdev->link);
                        return -1;
                }
        }
@@ -1642,7 +1620,7 @@ out:
 
 int lxc_netdev_set_mtu(const char *name, int mtu)
 {
-       int err, index, len;
+       int err, len;
        struct ifinfomsg *ifi;
        struct nl_handler nlh;
        struct nlmsg *answer = NULL, *nlmsg = NULL;
@@ -1665,11 +1643,6 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
        if (!answer)
                goto out;
 
-       err = -EINVAL;
-       index = if_nametoindex(name);
-       if (!index)
-               goto out;
-
        nlmsg->nlmsghdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
        nlmsg->nlmsghdr->nlmsg_type = RTM_NEWLINK;
 
@@ -1679,7 +1652,9 @@ int lxc_netdev_set_mtu(const char *name, int mtu)
                goto out;
        }
        ifi->ifi_family = AF_UNSPEC;
-       ifi->ifi_index = index;
+
+       if (nla_put_string(nlmsg, IFLA_IFNAME, name))
+               goto out;
 
        if (nla_put_u32(nlmsg, IFLA_MTU, mtu))
                goto out;
@@ -1702,7 +1677,7 @@ int lxc_netdev_down(const char *name)
        return netdev_set_flag(name, 0);
 }
 
-int lxc_veth_create(const char *name1, const char *name2)
+int lxc_veth_create(const char *name1, const char *name2, pid_t pid, unsigned int mtu)
 {
        int err, len;
        struct ifinfomsg *ifi;
@@ -1766,6 +1741,12 @@ int lxc_veth_create(const char *name1, const char *name2)
        if (nla_put_string(nlmsg, IFLA_IFNAME, name2))
                goto out;
 
+       if (mtu > 0 && nla_put_u32(nlmsg, IFLA_MTU, mtu))
+               goto out;
+
+       if (pid > 0 && nla_put_u32(nlmsg, IFLA_NET_NS_PID, pid))
+               goto out;
+
        nla_end_nested(nlmsg, nest3);
        nla_end_nested(nlmsg, nest2);
        nla_end_nested(nlmsg, nest1);
@@ -3926,6 +3907,7 @@ int lxc_network_recv_from_parent(struct lxc_handler *handler)
                ret = lxc_recv_nointr(data_sock, netdev->created_name, IFNAMSIZ, 0);
                if (ret < 0)
                        return -1;
+
                TRACE("Received network device name \"%s\" from parent", netdev->created_name);
        }
 
index 025a56152e55f1484a690a30643e26d9e641b75e..2cf1cbb0d0b43627470da932fcb6f9a779b5abd4 100644 (file)
@@ -203,7 +203,8 @@ extern int lxc_netdev_down(const char *name);
 extern int lxc_netdev_set_mtu(const char *name, int mtu);
 
 /* Create a virtual network devices. */
-extern int lxc_veth_create(const char *name1, const char *name2);
+extern int lxc_veth_create(const char *name1, const char *name2, pid_t pid,
+                          unsigned int mtu);
 extern int lxc_macvlan_create(const char *master, const char *name, int mode);
 extern int lxc_vlan_create(const char *master, const char *name,
                           unsigned short vid);