]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
container: introduce two functions named as {at/de}tach_interface().
authorDongsheng Yang <yangds.fnst@cn.fujitsu.com>
Fri, 10 Oct 2014 02:57:13 +0000 (10:57 +0800)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 15 Oct 2014 10:17:19 +0000 (12:17 +0200)
Currently, we depends on ip command to attach interface to container.
It means we only implemented it by python.

This patch implement adding and removing interface by c and added
them in struct container.

Changelog: 10/15/2014 (serge): return error if ifname is NULL.

Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com>
Acked-by: Serge E. Hallyn <serge.hallyn@ubuntu.com>
src/lxc/lxccontainer.c

index 47f60d9bf61ba93fb05ac4ae6a71e087e08a30bd..6b854338b53f1ddb78e171b64efe94b79476c394 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <lxc/lxccontainer.h>
 #include <lxc/version.h>
+#include <lxc/network.h>
 
 #include "config.h"
 #include "lxc.h"
@@ -3426,6 +3427,99 @@ static bool lxcapi_remove_device_node(struct lxc_container *c, const char *src_p
        return add_remove_device_node(c, src_path, dest_path, false);
 }
 
+static bool lxcapi_attach_interface(struct lxc_container *c, const char *ifname,
+                               const char *dst_ifname)
+{
+       int ret = 0;
+       if (am_unpriv()) {
+               ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
+               return false;
+       }
+
+       if (!ifname) {
+               ERROR("No source interface name given");
+               return false;
+       }
+
+       ret = lxc_netdev_isup(ifname);
+       if (ret < 0)
+               goto err;
+
+       /* netdev of ifname is up. */
+       if (ret) {
+               ret = lxc_netdev_down(ifname);
+               if (ret)
+                       goto err;
+       }
+
+       ret = lxc_netdev_move_by_name(ifname, c->init_pid(c), dst_ifname);
+       if (ret)
+               goto err;
+
+       return true;
+err:
+       /* -EINVAL means there is no netdev named as ifanme. */
+       if (ret == -EINVAL) {
+               ERROR("No network device named as %s.", ifname);
+       }
+       return false;
+}
+
+static bool lxcapi_detach_interface(struct lxc_container *c, const char *ifname,
+                                       const char *dst_ifname)
+{
+       pid_t pid, pid_outside;
+
+       if (am_unpriv()) {
+               ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
+               return false;
+       }
+
+       if (!ifname) {
+               ERROR("No source interface name given");
+               return false;
+       }
+
+       pid_outside = getpid();
+       pid = fork();
+       if (pid < 0) {
+               ERROR("failed to fork task to get interfaces information");
+               return false;
+       }
+
+       if (pid == 0) { // child
+               int ret = 0;
+               if (!enter_to_ns(c)) {
+                       ERROR("failed to enter namespace");
+                       exit(-1);
+               }
+
+               ret = lxc_netdev_isup(ifname);
+               if (ret < 0)
+                       exit(ret);
+
+               /* netdev of ifname is up. */
+               if (ret) {
+                       ret = lxc_netdev_down(ifname);
+                       if (ret)
+                               exit(ret);
+               }
+
+               ret = lxc_netdev_move_by_name(ifname, pid_outside, dst_ifname);
+
+               /* -EINVAL means there is no netdev named as ifanme. */
+               if (ret == -EINVAL) {
+                       ERROR("No network device named as %s.", ifname);
+               }
+               exit(ret);
+       }
+
+       if (wait_for_pid(pid) != 0)
+               return false;
+
+       return true;
+}
+
 struct criu_opts {
        /* The type of criu invocation, one of "dump" or "restore" */
        char *action;
@@ -4051,6 +4145,8 @@ struct lxc_container *lxc_container_new(const char *name, const char *configpath
        c->may_control = lxcapi_may_control;
        c->add_device_node = lxcapi_add_device_node;
        c->remove_device_node = lxcapi_remove_device_node;
+       c->attach_interface = lxcapi_attach_interface;
+       c->detach_interface = lxcapi_detach_interface;
        c->checkpoint = lxcapi_checkpoint;
        c->restore = lxcapi_restore;