From: Jamal Hadi Salim Date: Tue, 15 Dec 2009 09:14:27 +0000 (+0100) Subject: Add VLAN support in config X-Git-Tag: lxc-0.6.5~52 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=26c390288bbe04bbaba26f4ec1bbe68cb9d2b602;p=thirdparty%2Flxc.git Add VLAN support in config This adds ability to migrate vlan interfaces into namespaces by specifying them in a config Signed-off-by: Jamal Hadi Salim Acked-by: Daniel Lezcano Signed-off-by: Daniel Lezcano --- diff --git a/configure.ac b/configure.ac index ed58cf484..77d815368 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/doc/examples/Makefile.am b/doc/examples/Makefile.am index 0490a8b21..d68e192be 100644 --- a/doc/examples/Makefile.am +++ b/doc/examples/Makefile.am @@ -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 index 000000000..440443933 --- /dev/null +++ b/doc/examples/lxc-vlan.conf.in @@ -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 diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 81bc470f6..3550f3866 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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); diff --git a/src/lxc/conf.h b/src/lxc/conf.h index bb38206aa..3f9aac0b4 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -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; }; diff --git a/src/lxc/confile.c b/src/lxc/confile.c index 3a9a86d86..386af368b 100644 --- a/src/lxc/confile.c +++ b/src/lxc/confile.c @@ -33,6 +33,7 @@ #include #include "parse.h" +#include "utils.h" #include #include @@ -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) { diff --git a/src/lxc/lxc-checkconfig.in b/src/lxc/lxc-checkconfig.in index b02555c9c..3cc7608bc 100755 --- a/src/lxc/lxc-checkconfig.in +++ b/src/lxc/lxc-checkconfig.in @@ -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 diff --git a/src/lxc/network.c b/src/lxc/network.c index 57f9331ec..5fd663713 100644 --- a/src/lxc/network.c +++ b/src/lxc/network.c @@ -63,6 +63,10 @@ # 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; diff --git a/src/lxc/network.h b/src/lxc/network.h index 0534ec41b..d89dfae68 100644 --- a/src/lxc/network.h +++ b/src/lxc/network.h @@ -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 */