]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
add macvlan vepa and bridge mode
authorDaniel Lezcano <daniel.lezcano@free.fr>
Mon, 28 Dec 2009 21:10:11 +0000 (22:10 +0100)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Mon, 28 Dec 2009 21:10:11 +0000 (22:10 +0100)
The future kernel 2.6.33 will incorporate the macvlan bridge
mode where all the macvlan will be able to communicate if they are
using the same physical interface. This is an interesting feature
to have containers to communicate together. If we are outside of the
container, we have to setup a macvlan on the same physical interface than
the containers and use it to communicate with them.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
configure.ac
doc/lxc.conf.sgml.in
src/lxc/conf.c
src/lxc/conf.h
src/lxc/confile.c
src/lxc/network.c
src/lxc/network.h

index a634e8604e6131573dd3d1415213cf172d2f9504..0cd8e95227fc2b326590e6e091daf48982ec673c 100644 (file)
@@ -44,7 +44,7 @@ AS_AC_EXPAND(DOCDIR, $docdir)
 AC_ARG_WITH([config-path],
        [AC_HELP_STRING(
                [--with-config-path=dir],
-               [lxc configuration repository]
+               [lxc configuration repository path]
        )], [], [with_config_path="${localstatedir}/lib/lxc"])
 
 AS_AC_EXPAND(LXC_GENERATE_DATE, "$(date)")
index c12833361b6fb4ec7c98a319c6b524ac705a1bcf..fd618165f95832d18f6a3e34ea23cb5e09e56640 100644 (file)
@@ -134,11 +134,28 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
            <para>
              <option>veth:</option> a new network stack is created, a
              peer network device is created with one side assigned to
-             the container and the other side attached to a bridge
-             specified by the <option>lxc.network.link</option>. The
-             bridge has to be setup before on the
-             system, <command>lxc</command> won't handle
-             configuration outside of the container.
+             the container and the other side is attached to a bridge
+             specified by the <option>lxc.network.link</option>. If
+             the bridge is not specified, then the veth pair device
+             will be created but not attached to any
+             bridge. Otherwise, the bridge has to be setup before on
+             the system, <command>lxc</command> won't handle
+             any configuration outside of the container.  By
+             default <command>lxc</command> choose a name for the
+             network device belonging to the outside of the
+             container, this name is handled
+             by <command>lxc</command>, but if you wish to handle
+             this name yourself, you can tell <command>lxc</command>
+             to set a specific name with
+             the <option>lxc.network.veth.pair</option> option.
+           </para>
+
+           <para>
+             <option>vlan:</option> a new network stack is created, a
+             vlan interface is linked with the interface specified by
+             the <option>lxc.network.link</option> and assigned to
+             the container. The vlan identifier is specified with the
+             option <option>lxc.network.vlan.id</option>.
            </para>
 
            <para>
@@ -147,11 +164,33 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
              interface specified by
              the <option>lxc.network.link</option> and assigned to
              the container.
+             <option>lxc.network.macvlan.mode</option> specifies the
+             mode the macvlan will use to communicate between
+             different macvlan on the same upper device. The accepted
+             modes are <option>private</option>, the device never
+             communicates with any other device on the same upper_dev (default),
+             <option>vepa</option>, the new Virtual Ethernet Port
+             Aggregator (VEPA) mode, it assumes that the adjacent
+             bridge returns all frames where both source and
+             destination are local to the macvlan port, i.e. the
+             bridge is set up as a reflective relay.  Broadcast
+             frames coming in from the upper_dev get flooded to all
+             macvlan interfaces in VEPA mode, local frames are not
+             delivered locallay, or <option>bridge</option>, it
+             provides the behavior of a simple bridge between
+             different macvlan interfaces on the same port. Frames
+             from one interface to another one get delivered directly
+             and are not sent out externally. Broadcast frames get
+             flooded to all other bridge ports and to the external
+             interface, but when they come back from a reflective
+             relay, we don't deliver them again.  Since we know all
+             the MAC addresses, the macvlan bridge mode does not
+             require learning or STP like the bridge module does.
            </para>
 
            <para>
              <option>phys:</option> a new network stack is created
-             and the interface specified by
+             and an already existing interface specified by
              the <option>lxc.network.link</option> is assigned to the
              container.
            </para>
index 98a263b8f8335048c786886c8aaaeebcf8a0560b..da7c945d836f0e6f946371f440ffc1f23e7b32e7 100644 (file)
@@ -834,8 +834,8 @@ static int instanciate_veth(struct lxc_netdev *netdev)
        char veth1buf[IFNAMSIZ], *veth1;
        char veth2[IFNAMSIZ];
 
-       if (netdev->priv.pair)
-               veth1 = netdev->priv.pair;
+       if (netdev->priv.veth_attr.pair)
+               veth1 = netdev->priv.veth_attr.pair;
        else {
                snprintf(veth1buf, sizeof(veth1buf), "vethXXXXXX");
                mktemp(veth1buf);
@@ -911,7 +911,8 @@ static int instanciate_macvlan(struct lxc_netdev *netdev)
                return -1;
        }
 
-       if (lxc_macvlan_create(netdev->link, peer)) {
+       if (lxc_macvlan_create(netdev->link, peer,
+                              netdev->priv.macvlan_attr.mode)) {
                ERROR("failed to create macvlan interface '%s' on '%s'",
                      peer, netdev->link);
                return -1;
@@ -924,7 +925,8 @@ static int instanciate_macvlan(struct lxc_netdev *netdev)
                return -1;
        }
 
-       DEBUG("instanciated macvlan '%s', index is '%d'", peer, netdev->ifindex);
+       DEBUG("instanciated macvlan '%s', index is '%d' and mode '%d'",
+             peer, netdev->ifindex, netdev->priv.macvlan_attr.mode);
 
        return 0;
 }
@@ -939,7 +941,7 @@ static int instanciate_vlan(struct lxc_netdev *netdev)
                return -1;
        }
 
-       snprintf(peer, sizeof(peer), "vlan%d",netdev->priv.vlan_attr.vid);
+       snprintf(peer, sizeof(peer), "vlan%d", netdev->priv.vlan_attr.vid);
 
        if (lxc_vlan_create(netdev->link, peer, netdev->priv.vlan_attr.vid)) {
                ERROR("failed to create vlan interface '%s' on '%s'",
@@ -954,7 +956,9 @@ static int instanciate_vlan(struct lxc_netdev *netdev)
                return -1;
        }
 
-       DEBUG("instanciated vlan '%s', ifindex is '%d'", "vlan1000", netdev->ifindex);
+       DEBUG("instanciated vlan '%s', ifindex is '%d'", " vlan1000",
+             netdev->ifindex);
+
        return 0;
 }
 
index 8e01d921fabaf1ad183a02b9e6dba529900e806c..8548eeb538cf6954f5fe6fe7dd7d419d0ba679d6 100644 (file)
@@ -71,6 +71,10 @@ struct lxc_route6 {
        struct in6_addr addr;
 };
 
+struct ifla_veth {
+       char *pair; /* pair name */
+};
+
 struct ifla_vlan {
        uint   flags;
        uint   fmask;
@@ -78,9 +82,14 @@ struct ifla_vlan {
        ushort   pad;
 };
 
+struct ifla_macvlan {
+       int mode; /* private, vepa, bridge */
+};
+
 union netdev_p {
-       char *pair;
+       struct ifla_veth veth_attr;
        struct ifla_vlan vlan_attr;
+       struct ifla_macvlan macvlan_attr;
 };
 
 /*
index 3593b9a88b2d7ed0d18048991b490e9ef8177006..a5b626378e7178e49dcc4728103c773582a33456 100644 (file)
@@ -50,9 +50,10 @@ static int config_network_type(const char *, char *, struct lxc_conf *);
 static int config_network_flags(const char *, char *, struct lxc_conf *);
 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_veth_pair(const char *, char *, struct lxc_conf *);
+static int config_network_macvlan_mode(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_vlan_id(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 *);
@@ -66,22 +67,23 @@ struct config {
 
 static struct config config[] = {
 
-       { "lxc.pts",            config_pts            },
-       { "lxc.tty",            config_tty            },
-       { "lxc.cgroup",         config_cgroup         },
-       { "lxc.mount",          config_mount          },
-       { "lxc.rootfs",         config_rootfs         },
-       { "lxc.utsname",        config_utsname        },
-       { "lxc.network.type",   config_network_type   },
-       { "lxc.network.flags",  config_network_flags  },
-       { "lxc.network.link",   config_network_link   },
-       { "lxc.network.name",   config_network_name   },
-       { "lxc.network.veth.pair",   config_network_pair   },
-       { "lxc.network.hwaddr", config_network_hwaddr },
-       { "lxc.network.mtu",    config_network_mtu    },
-       { "lxc.network.vlan.id", config_network_vlanid },
-       { "lxc.network.ipv4",   config_network_ipv4   },
-       { "lxc.network.ipv6",   config_network_ipv6   },
+       { "lxc.pts",                  config_pts                  },
+       { "lxc.tty",                  config_tty                  },
+       { "lxc.cgroup",               config_cgroup               },
+       { "lxc.mount",                config_mount                },
+       { "lxc.rootfs",               config_rootfs               },
+       { "lxc.utsname",              config_utsname              },
+       { "lxc.network.type",         config_network_type         },
+       { "lxc.network.flags",        config_network_flags        },
+       { "lxc.network.link",         config_network_link         },
+       { "lxc.network.name",         config_network_name         },
+       { "lxc.network.macvlan.mode", config_network_macvlan_mode },
+       { "lxc.network.veth.pair",    config_network_veth_pair    },
+       { "lxc.network.hwaddr",       config_network_hwaddr       },
+       { "lxc.network.mtu",          config_network_mtu          },
+       { "lxc.network.vlan.id",      config_network_vlan_id      },
+       { "lxc.network.ipv4",         config_network_ipv4         },
+       { "lxc.network.ipv6",         config_network_ipv6         },
 };
 
 static const size_t config_size = sizeof(config)/sizeof(struct config);
@@ -97,7 +99,8 @@ static struct config *getconfig(const char *key)
        return NULL;
 }
 
-static int config_network_type(const char *key, char *value, struct lxc_conf *lxc_conf)
+static int config_network_type(const char *key, char *value,
+                              struct lxc_conf *lxc_conf)
 {
        struct lxc_list *network = &lxc_conf->network;
        struct lxc_netdev *netdev;
@@ -190,6 +193,42 @@ static int network_ifname(char **valuep, char *value)
        return 0;
 }
 
+#ifndef MACVLAN_MODE_PRIVATE
+#  define MACVLAN_MODE_PRIVATE 1
+#endif
+
+#ifndef MACVLAN_MODE_VEPA
+#  define MACVLAN_MODE_VEPA 2
+#endif
+
+#ifndef MACVLAN_MODE_BRIDGE
+#  define MACVLAN_MODE_BRIDGE 4
+#endif
+
+static int macvlan_mode(int *valuep, char *value)
+{
+       struct mc_mode {
+               char *name;
+               int mode;
+       } m[] = {
+               { "private", MACVLAN_MODE_PRIVATE },
+               { "vepa", MACVLAN_MODE_VEPA },
+               { "bridge", MACVLAN_MODE_BRIDGE },
+       };
+
+       int i;
+
+       for (i = 0; i < sizeof(m)/sizeof(m[0]); i++) {
+               if (strcmp(m[i].name, value))
+                       continue;
+
+               *valuep = m[i].mode;
+               return 0;
+       }
+
+       return -1;
+}
+
 static int config_network_flags(const char *key, char *value,
                                struct lxc_conf *lxc_conf)
 {
@@ -228,8 +267,20 @@ static int config_network_name(const char *key, char *value,
        return network_ifname(&netdev->name, value);
 }
 
-static int config_network_pair(const char *key, char *value,
-                              struct lxc_conf *lxc_conf)
+static int config_network_veth_pair(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;
+
+       return network_ifname(&netdev->priv.veth_attr.pair, value);
+}
+
+static int config_network_macvlan_mode(const char *key, char *value,
+                                      struct lxc_conf *lxc_conf)
 {
        struct lxc_netdev *netdev;
 
@@ -237,7 +288,7 @@ static int config_network_pair(const char *key, char *value,
        if (!netdev)
                return -1;
 
-       return network_ifname(&netdev->priv.pair, value);
+       return macvlan_mode(&netdev->priv.macvlan_attr.mode, value);
 }
 
 static int config_network_hwaddr(const char *key, char *value,
@@ -258,7 +309,7 @@ static int config_network_hwaddr(const char *key, char *value,
        return 0;
 }
 
-static int config_network_vlanid(const char *key, char *value,
+static int config_network_vlan_id(const char *key, char *value,
                               struct lxc_conf *lxc_conf)
 {
        struct lxc_netdev *netdev;
@@ -359,7 +410,8 @@ static int config_network_ipv4(const char *key, char *value,
        return 0;
 }
 
-static int config_network_ipv6(const char *key, char *value, struct lxc_conf *lxc_conf)
+static int config_network_ipv6(const char *key, char *value,
+                              struct lxc_conf *lxc_conf)
 {
        struct lxc_netdev *netdev;
        struct lxc_inet6dev *inet6dev;
index 5fd663713f86de412a6ef88372d1efee5dc159e2..82f3ae7d79783dca6d586b78edb5b00f49c647ef 100644 (file)
 # define VETH_INFO_PEER 1
 #endif
 
+#ifndef IFLA_MACVLAN_MODE
+# define IFLA_MACVLAN_MODE 1
+#endif
+
 struct link_req {
        struct nlmsg nlmsg;
        struct ifinfomsg ifinfomsg;
@@ -445,8 +449,10 @@ int lxc_vlan_create(const char *master, const char *name, ushort vlanid)
        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);
@@ -470,12 +476,12 @@ err3:
        return err;
 }
 
-int lxc_macvlan_create(const char *master, const char *name)
+int lxc_macvlan_create(const char *master, const char *name, int mode)
 {
        struct nl_handler nlh;
        struct nlmsg *nlmsg = NULL, *answer = NULL;
        struct link_req *link_req;
-       struct rtattr *nest;
+       struct rtattr *nest, *nest2;
        int index, len, err = -1;
 
        if (netlink_open(&nlh, NETLINK_ROUTE))
@@ -515,6 +521,17 @@ int lxc_macvlan_create(const char *master, const char *name)
        if (nla_put_string(nlmsg, IFLA_INFO_KIND, "macvlan"))
                goto out;
 
+       if (mode) {
+               nest2 = nla_begin_nested(nlmsg, IFLA_INFO_DATA);
+               if (!nest2)
+                       goto out;
+
+               if (nla_put_u32(nlmsg, IFLA_MACVLAN_MODE, mode))
+                       goto out;
+
+               nla_end_nested(nlmsg, nest2);
+       }
+
        nla_end_nested(nlmsg, nest);
 
        if (nla_put_u32(nlmsg, IFLA_LINK, index))
index d89dfae6811aa5ff6c80973d555784213c5f3543..7bac5ee5ef4dadda4925bbc290d0330121f6eb2a 100644 (file)
@@ -66,7 +66,7 @@ extern int lxc_veth_create(const char *name1, const char *name2);
 /* 
  * Create a macvlan network device
  */
-extern int lxc_macvlan_create(const char *master, const char *name);
+extern int lxc_macvlan_create(const char *master, const char *name, int mode);
 
 /*
  * Create a vlan network device