Commit e892973e by Daniel Lezcano Committed by Daniel Lezcano

add macvlan vepa and bridge mode

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: 's avatarDaniel Lezcano <dlezcano@fr.ibm.com>
parent eb960fea
......@@ -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)")
......
......@@ -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>
......
......@@ -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;
}
......
......@@ -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;
};
/*
......
......@@ -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;
......
......@@ -75,6 +75,10 @@
# 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))
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment