]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Add VLAN support in config
authorJamal Hadi Salim <hadi@cyberus.ca>
Tue, 15 Dec 2009 09:14:27 +0000 (10:14 +0100)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Tue, 15 Dec 2009 09:14:27 +0000 (10:14 +0100)
This adds ability to migrate vlan interfaces into namespaces
by specifying them in a config

Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
Acked-by: Daniel Lezcano <daniel.lezcano@free.fr>
Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
configure.ac
doc/examples/Makefile.am
doc/examples/lxc-vlan.conf.in [new file with mode: 0644]
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/lxc-checkconfig.in
src/lxc/network.c
src/lxc/network.h

index ed58cf484e63f42f6a7bfb7df9dff87fad660242..77d81536887b22b7e8d18ddb192b0bd1d5a402fe 100644 (file)
@@ -102,6 +102,7 @@ AC_CONFIG_FILES([
 
        doc/examples/Makefile
        doc/examples/lxc-macvlan.conf
+       doc/examples/lxc-vlan.conf
        doc/examples/lxc-no-netns.conf
        doc/examples/lxc-empty-netns.conf
        doc/examples/lxc-phys.conf
index 0490a8b2100441e7f530b07fb35ae5303bad391a..d68e192bed53687d8f348e674867c8ad7e237bda 100644 (file)
@@ -5,6 +5,7 @@ pkgexamplesdir=$(docdir)/examples
 
 pkgexamples_DATA = \
        lxc-macvlan.conf \
+       lxc-vlan.conf \
        lxc-no-netns.conf \
        lxc-empty-netns.conf \
        lxc-phys.conf \
@@ -14,6 +15,7 @@ endif
 
 noinst_DATA = \
        lxc-macvlan.conf.in \
+       lxc-vlan.conf.in \
        lxc-empty-netns.conf.in \
        lxc-no-netns.conf.in \
        lxc-phys.conf.in \
diff --git a/doc/examples/lxc-vlan.conf.in b/doc/examples/lxc-vlan.conf.in
new file mode 100644 (file)
index 0000000..4404439
--- /dev/null
@@ -0,0 +1,9 @@
+# Container with network virtualized using the vlan device driver
+lxc.utsname = alpha
+lxc.network.type = vlan
+lxc.network.vlan.id = 1234
+lxc.network.flags = up
+lxc.network.link = eth0
+lxc.network.hwaddr = 4a:49:43:49:79:bd
+lxc.network.ipv4 = 1.2.3.4/24
+lxc.network.ipv6 = 2003:db8:1:0:214:1234:fe0b:3596
index 81bc470f6555c7bab5c4b3caea63f20d7c7553ce..3550f386639ee7f31febbf7a2dd2b67ea4303d37 100644 (file)
@@ -75,12 +75,14 @@ struct mount_opt {
 
 static int instanciate_veth(struct lxc_netdev *);
 static int instanciate_macvlan(struct lxc_netdev *);
+static int instanciate_vlan(struct lxc_netdev *);
 static int instanciate_phys(struct lxc_netdev *);
 static int instanciate_empty(struct lxc_netdev *);
 
 static  instanciate_cb netdev_conf[MAXCONFTYPE + 1] = {
        [VETH]    = instanciate_veth,
        [MACVLAN] = instanciate_macvlan,
+       [VLAN]    = instanciate_vlan,
        [PHYS]    = instanciate_phys,
        [EMPTY]   = instanciate_empty,
 };
@@ -927,6 +929,35 @@ static int instanciate_macvlan(struct lxc_netdev *netdev)
        return 0;
 }
 
+/* XXX: merge with instanciate_macvlan */
+static int instanciate_vlan(struct lxc_netdev *netdev)
+{
+       char peer[IFNAMSIZ];
+
+       if (!netdev->link) {
+               ERROR("no link specified for vlan netdev");
+               return -1;
+       }
+
+       snprintf(peer, sizeof(peer), "vlan%d",netdev->vlan_attr.vid);
+
+       if (lxc_vlan_create(netdev->link, peer, netdev->vlan_attr.vid)) {
+               ERROR("failed to create vlan interface '%s' on '%s'",
+                     peer, netdev->link);
+               return -1;
+       }
+
+       netdev->ifindex = if_nametoindex(peer);
+       if (!netdev->ifindex) {
+               ERROR("failed to retrieve the ifindex for %s", peer);
+               lxc_device_delete(peer);
+               return -1;
+       }
+
+       DEBUG("instanciated vlan '%s', ifindex is '%d'", "vlan1000", netdev->ifindex);
+       return 0;
+}
+
 static int instanciate_phys(struct lxc_netdev *netdev)
 {
        netdev->ifindex = if_nametoindex(netdev->link);
index bb38206aa7840690e2206ac41d26cc8673e53f6b..3f9aac0b48b65a4a7e3de475a28becc48bad5cd5 100644 (file)
@@ -33,6 +33,7 @@ enum {
        VETH,
        MACVLAN,
        PHYS,
+       VLAN,
        MAXCONFTYPE,
 };
 
@@ -69,6 +70,14 @@ struct lxc_inet6dev {
 struct lxc_route6 {
        struct in6_addr addr;
 };
+
+struct ifla_vlan {
+       uint   flags;
+       uint   fmask;
+       ushort   vid;
+       ushort   pad;
+};
+
 /*
  * Defines a structure to configure a network device
  * @link   : lxc.network.link, name of bridge or host iface to attach if any
@@ -87,6 +96,7 @@ struct lxc_netdev {
        char *pair;
        char *hwaddr;
        char *mtu;
+       struct ifla_vlan vlan_attr;
        struct lxc_list ipv4;
        struct lxc_list ipv6;
 };
index 3a9a86d868458f8286ff7ea58de9c7129dc3fac6..386af368bb51e6340810d2fc7da156094ced59fe 100644 (file)
@@ -33,6 +33,7 @@
 #include <net/if.h>
 
 #include "parse.h"
+#include "utils.h"
 
 #include <lxc/log.h>
 #include <lxc/conf.h>
@@ -51,6 +52,7 @@ static int config_network_link(const char *, char *, struct lxc_conf *);
 static int config_network_name(const char *, char *, struct lxc_conf *);
 static int config_network_pair(const char *, char *, struct lxc_conf *);
 static int config_network_hwaddr(const char *, char *, struct lxc_conf *);
+static int config_network_vlanid(const char *, char *, struct lxc_conf *);
 static int config_network_mtu(const char *, char *, struct lxc_conf *);
 static int config_network_ipv4(const char *, char *, struct lxc_conf *);
 static int config_network_ipv6(const char *, char *, struct lxc_conf *);
@@ -77,6 +79,7 @@ static struct config config[] = {
        { "lxc.network.pair",   config_network_pair   },
        { "lxc.network.hwaddr", config_network_hwaddr },
        { "lxc.network.mtu",    config_network_mtu    },
+       { "lxc.network.vlanid", config_network_vlanid },
        { "lxc.network.ipv4",   config_network_ipv4   },
        { "lxc.network.ipv6",   config_network_ipv6   },
 };
@@ -125,6 +128,8 @@ static int config_network_type(const char *key, char *value, struct lxc_conf *lx
                netdev->type = VETH;
        else if (!strcmp(value, "macvlan"))
                netdev->type = MACVLAN;
+       else if (!strcmp(value, "vlan"))
+               netdev->type = VLAN;
        else if (!strcmp(value, "phys"))
                netdev->type = PHYS;
        else if (!strcmp(value, "empty"))
@@ -253,6 +258,21 @@ static int config_network_hwaddr(const char *key, char *value,
        return 0;
 }
 
+static int config_network_vlanid(const char *key, char *value,
+                              struct lxc_conf *lxc_conf)
+{
+       struct lxc_netdev *netdev;
+
+       netdev = network_netdev(key, value, &lxc_conf->network);
+       if (!netdev)
+               return -1;
+
+       if (get_u16(&netdev->vlan_attr.vid, value, 0))
+               return -1;
+
+       return 0;
+}
+
 static int config_network_mtu(const char *key, char *value,
                              struct lxc_conf *lxc_conf)
 {
index b02555c9c39df3be249e8d984950d87552cecb8f..3cc7608bc2bace52a25bee2edf3d71fabe4c5364 100755 (executable)
@@ -65,4 +65,5 @@ echo
 echo "--- Misc ---"
 echo -n "Veth pair device: " && is_enabled CONFIG_VETH
 echo -n "Macvlan: " && is_enabled CONFIG_MACVLAN
+echo -n "Vlan: " && is_enabled CONFIG_VLAN_8021Q
 echo -n "File capabilities: " && is_enabled CONFIG_SECURITY_FILE_CAPABILITIES
index 57f9331ecd621f7801481e7f8377da574196b298..5fd663713f86de412a6ef88372d1efee5dc159e2 100644 (file)
 # define IFLA_INFO_KIND 1
 #endif
 
+#ifndef IFLA_VLAN_ID
+# define IFLA_VLAN_ID 1
+#endif
+
 #ifndef IFLA_INFO_DATA
 #  define IFLA_INFO_DATA 2
 #endif
@@ -392,6 +396,80 @@ out:
        return err;
 }
 
+/* XXX: merge with lxc_macvlan_create */
+int lxc_vlan_create(const char *master, const char *name, ushort vlanid)
+{
+       struct nl_handler nlh;
+       struct nlmsg *nlmsg = NULL, *answer = NULL;
+       struct link_req *link_req;
+       struct rtattr *nest, *nest2;
+       int lindex, len, err = -1;
+
+       if (netlink_open(&nlh, NETLINK_ROUTE))
+               return -1;
+
+       len = strlen(master);
+       if (len == 1 || len > IFNAMSIZ)
+               goto err3;
+
+       len = strlen(name);
+       if (len == 1 || len > IFNAMSIZ)
+               goto err3;
+
+       nlmsg = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       if (!nlmsg)
+               goto err3;
+
+       answer = nlmsg_alloc(NLMSG_GOOD_SIZE);
+       if (!answer)
+               goto err2;
+
+       lindex = if_nametoindex(master);
+       if (!lindex)
+               goto err1;
+
+       link_req = (struct link_req *)nlmsg;
+       link_req->ifinfomsg.ifi_family = AF_UNSPEC;
+       nlmsg->nlmsghdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+       nlmsg->nlmsghdr.nlmsg_flags =
+               NLM_F_REQUEST|NLM_F_CREATE|NLM_F_EXCL|NLM_F_ACK;
+       nlmsg->nlmsghdr.nlmsg_type = RTM_NEWLINK;
+
+       nest = nla_begin_nested(nlmsg, IFLA_LINKINFO);
+       if (!nest)
+               goto err1;
+
+       if (nla_put_string(nlmsg, IFLA_INFO_KIND, "vlan"))
+               goto err1;
+
+       nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
+       if (!nest2)
+               goto err1;
+       if (nla_put_u16(nlmsg, IFLA_VLAN_ID, vlanid))
+               goto err1;
+       nla_end_nested(nlmsg, nest2);
+
+       nla_end_nested(nlmsg, nest);
+
+       if (nla_put_u32(nlmsg, IFLA_LINK, lindex))
+               goto err1;
+
+       if (nla_put_string(nlmsg, IFLA_IFNAME, name))
+               goto err1;
+
+       if (netlink_transaction(&nlh, nlmsg, answer))
+               goto err1;
+
+       err = 0;
+err1:
+       nlmsg_free(answer);
+err2:
+       nlmsg_free(nlmsg);
+err3:
+       netlink_close(&nlh);
+       return err;
+}
+
 int lxc_macvlan_create(const char *master, const char *name)
 {
        struct nl_handler nlh;
index 0534ec41bbac268fa1bbc8949b3abc758fbbbdfd..d89dfae6811aa5ff6c80973d555784213c5f3543 100644 (file)
@@ -68,6 +68,11 @@ extern int lxc_veth_create(const char *name1, const char *name2);
  */
 extern int lxc_macvlan_create(const char *master, const char *name);
 
+/*
+ * Create a vlan network device
+ */
+extern int lxc_vlan_create(const char *master, const char *name, ushort vid);
+
 /*
  * Activate forwarding
  */