Skip to content

Commit

Permalink
network: Adds support host side veth device static routes
Browse files Browse the repository at this point in the history
Adds the following new config keys:

	lxc.net.[i].veth.ipv4.route
	lxc.net.[i].veth.ipv6.route
E.g.

	lxc.net.0.veth.ipv4.route = 192.0.2.1/32
	lxc.net.0.veth.ipv4.route = 192.0.3.0/24
	lxc.net.0.veth.ipv6.route = 2001:db8::1/128
	lxc.net.0.veth.ipv6.route = 2001:db8:2::/64

Signed-off-by: tomponline <thomas.parrott@canonical.com>
  • Loading branch information
tomponline committed Apr 29, 2019
1 parent 41cd8a8 commit d4a7da4
Show file tree
Hide file tree
Showing 8 changed files with 375 additions and 18 deletions.
6 changes: 6 additions & 0 deletions doc/api-extensions.md
Expand Up @@ -32,3 +32,9 @@ until a reboot succeeded. It takes a timeout argument. When set to `> 0`
This adds support for injecting and removing mounts into/from a running
containers. Two new API functions `mount()` and `umount()` are added. They
mirror the current mount and umount API of the kernel.

## network\_veth\_routes

This introduces the `lxc.net.[i].veth.ipv4.route` and `lxc.net.[i].veth.ipv6.route` properties
on `veth` type network interfaces. This allows adding static routes on host to the container's
network interface.
16 changes: 11 additions & 5 deletions doc/lxc.container.conf.sgml.in
Expand Up @@ -375,7 +375,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<listitem>
<para>
The only allowed values are 0 and 1. Set this to 1 to destroy a
container on shutdown.
container on shutdown.
</para>
</listitem>
</varlistentry>
Expand Down Expand Up @@ -459,6 +459,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
the <option>lxc.net.[i].veth.pair</option> option (except for
unprivileged containers where this option is ignored for security
reasons).

Static routes can be added on the host pointing to the container using the
<option>lxc.net.[i].veth.ipv4.route</option> and
<option>lxc.net.[i].veth.ipv6.route</option> options.
Several lines specify several routes.
The route is in format x.y.z.t/m, eg. 192.168.1.0/24.
</para>

<para>
Expand Down Expand Up @@ -855,7 +861,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
When manually specifying a size for the log file the value should
be a power of 2 when converted to bytes. Valid size prefixes are
'KB', 'MB', 'GB'. (Note that all conversions are based on multiples
of 1024. That means 'KB' == 'KiB', 'MB' == 'MiB', 'GB' == 'GiB'.
of 1024. That means 'KB' == 'KiB', 'MB' == 'MiB', 'GB' == 'GiB'.
Additionally, the case of the suffix is ignored, i.e. 'kB', 'KB' and
'Kb' are treated equally.)

Expand Down Expand Up @@ -1629,7 +1635,7 @@ dev/null proc/kcore none bind,relative 0 0
</para>

<para>
To inherit the namespace from another container set the
To inherit the namespace from another container set the
<option>lxc.namespace.share.[namespace identifier]</option> to the name of
the container, e.g. <option>lxc.namespace.share.pid=c3</option>.
</para>
Expand Down Expand Up @@ -1708,15 +1714,15 @@ dev/null proc/kcore none bind,relative 0 0
</term>
<listitem>
<para>
Specify the kernel parameters to be set. The parameters available
Specify the kernel parameters to be set. The parameters available
are those listed under /proc/sys/.
Note that not all sysctls are namespaced. Changing Non-namespaced
sysctls will cause the system-wide setting to be modified.
<citerefentry>
<refentrytitle><command>sysctl</command></refentrytitle>
<manvolnum>8</manvolnum>
</citerefentry>.
If used with no value, lxc will clear the parameters specified up
If used with no value, lxc will clear the parameters specified up
to this point.
</para>
</listitem>
Expand Down
1 change: 1 addition & 0 deletions src/lxc/api_extensions.h
Expand Up @@ -44,6 +44,7 @@ static char *api_extensions[] = {
"mount_injection_file",
"seccomp_allow_nesting",
"seccomp_notify",
"network_veth_routes",
};

static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions);
Expand Down
236 changes: 236 additions & 0 deletions src/lxc/confile.c
Expand Up @@ -137,6 +137,8 @@ lxc_config_define(net_script_down);
lxc_config_define(net_script_up);
lxc_config_define(net_type);
lxc_config_define(net_veth_pair);
lxc_config_define(net_veth_ipv4_route);
lxc_config_define(net_veth_ipv6_route);
lxc_config_define(net_vlan_id);
lxc_config_define(no_new_privs);
lxc_config_define(personality);
Expand Down Expand Up @@ -226,6 +228,8 @@ static struct lxc_config_t config_jump_table[] = {
{ "lxc.net.type", set_config_net_type, get_config_net_type, clr_config_net_type, },
{ "lxc.net.vlan.id", set_config_net_vlan_id, get_config_net_vlan_id, clr_config_net_vlan_id, },
{ "lxc.net.veth.pair", set_config_net_veth_pair, get_config_net_veth_pair, clr_config_net_veth_pair, },
{ "lxc.net.veth.ipv4.route", set_config_net_veth_ipv4_route, get_config_net_veth_ipv4_route, clr_config_net_veth_ipv4_route, },
{ "lxc.net.veth.ipv6.route", set_config_net_veth_ipv6_route, get_config_net_veth_ipv6_route, clr_config_net_veth_ipv6_route, },
{ "lxc.net.", set_config_net_nic, get_config_net_nic, clr_config_net_nic, },
{ "lxc.net", set_config_net, get_config_net, clr_config_net, },
{ "lxc.no_new_privs", set_config_no_new_privs, get_config_no_new_privs, clr_config_no_new_privs, },
Expand Down Expand Up @@ -289,6 +293,8 @@ static int set_config_net_type(const char *key, const char *value,

if (!strcmp(value, "veth")) {
netdev->type = LXC_NET_VETH;
lxc_list_init(&netdev->priv.veth_attr.ipv4_routes);
lxc_list_init(&netdev->priv.veth_attr.ipv6_routes);
} else if (!strcmp(value, "macvlan")) {
netdev->type = LXC_NET_MACVLAN;
lxc_macvlan_mode_to_flag(&netdev->priv.macvlan_attr.mode,
Expand Down Expand Up @@ -629,6 +635,69 @@ static int set_config_net_ipv4_gateway(const char *key, const char *value,
return 0;
}

static int set_config_net_veth_ipv4_route(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
__do_free char *valdup = NULL;
__do_free struct lxc_inetdev *inetdev = NULL;
__do_free struct lxc_list *list = NULL;
int ret;
char *netmask, *slash;
struct lxc_netdev *netdev = data;

if (lxc_config_value_empty(value))
return clr_config_net_veth_ipv4_route(key, lxc_conf, data);

if (!netdev)
return minus_one_set_errno(EINVAL);

if (netdev->type != LXC_NET_VETH) {
SYSERROR("Invalid ipv4 route \"%s\", can only be used with veth network", value);
return minus_one_set_errno(EINVAL);
}

inetdev = malloc(sizeof(*inetdev));
if (!inetdev)
return -1;
memset(inetdev, 0, sizeof(*inetdev));

list = malloc(sizeof(*list));
if (!list)
return -1;

lxc_list_init(list);
list->elem = inetdev;

valdup = strdup(value);
if (!valdup)
return -1;

slash = strchr(valdup, '/');
if (!slash)
return minus_one_set_errno(EINVAL);

*slash = '\0';
slash++;
if (*slash == '\0')
return minus_one_set_errno(EINVAL);

netmask = slash;

ret = lxc_safe_uint(netmask, &inetdev->prefix);
if (ret < 0 || inetdev->prefix > 32)
return minus_one_set_errno(EINVAL);

ret = inet_pton(AF_INET, valdup, &inetdev->addr);
if (!ret || ret < 0)
return minus_one_set_errno(EINVAL);

lxc_list_add_tail(&netdev->priv.veth_attr.ipv4_routes, list);
move_ptr(inetdev);
move_ptr(list);

return 0;
}

static int set_config_net_ipv6_address(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
Expand Down Expand Up @@ -733,6 +802,69 @@ static int set_config_net_ipv6_gateway(const char *key, const char *value,
return 0;
}

static int set_config_net_veth_ipv6_route(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
__do_free char *valdup;
__do_free struct lxc_inet6dev *inet6dev;
__do_free struct lxc_list *list;
int ret;
char *netmask, *slash;
struct lxc_netdev *netdev = data;

if (lxc_config_value_empty(value))
return clr_config_net_veth_ipv6_route(key, lxc_conf, data);

if (!netdev)
return minus_one_set_errno(EINVAL);

if (netdev->type != LXC_NET_VETH) {
SYSERROR("Invalid ipv6 route \"%s\", can only be used with veth network", value);
return minus_one_set_errno(EINVAL);
}

inet6dev = malloc(sizeof(*inet6dev));
if (!inet6dev)
return -1;
memset(inet6dev, 0, sizeof(*inet6dev));

list = malloc(sizeof(*list));
if (!list)
return -1;

lxc_list_init(list);
list->elem = inet6dev;

valdup = strdup(value);
if (!valdup)
return -1;

slash = strchr(valdup, '/');
if (!slash)
return minus_one_set_errno(EINVAL);

*slash = '\0';
slash++;
if (*slash == '\0')
return minus_one_set_errno(EINVAL);

netmask = slash;

ret = lxc_safe_uint(netmask, &inet6dev->prefix);
if (ret < 0 || inet6dev->prefix > 128)
return minus_one_set_errno(EINVAL);

ret = inet_pton(AF_INET6, valdup, &inet6dev->addr);
if (!ret || ret < 0)
return minus_one_set_errno(EINVAL);

lxc_list_add_tail(&netdev->priv.veth_attr.ipv6_routes, list);
move_ptr(inet6dev);
move_ptr(list);

return 0;
}

static int set_config_net_script_up(const char *key, const char *value,
struct lxc_conf *lxc_conf, void *data)
{
Expand Down Expand Up @@ -4898,6 +5030,24 @@ static int clr_config_net_ipv4_address(const char *key,
return 0;
}

static int clr_config_net_veth_ipv4_route(const char *key,
struct lxc_conf *lxc_conf, void *data)
{
struct lxc_netdev *netdev = data;
struct lxc_list *cur, *next;

if (!netdev)
return -1;

lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) {
lxc_list_del(cur);
free(cur->elem);
free(cur);
}

return 0;
}

static int clr_config_net_ipv6_gateway(const char *key,
struct lxc_conf *lxc_conf, void *data)
{
Expand Down Expand Up @@ -4930,6 +5080,24 @@ static int clr_config_net_ipv6_address(const char *key,
return 0;
}

static int clr_config_net_veth_ipv6_route(const char *key,
struct lxc_conf *lxc_conf, void *data)
{
struct lxc_netdev *netdev = data;
struct lxc_list *cur, *next;

if (!netdev)
return -1;

lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) {
lxc_list_del(cur);
free(cur->elem);
free(cur);
}

return 0;
}

static int get_config_net_nic(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
Expand Down Expand Up @@ -5274,6 +5442,39 @@ static int get_config_net_ipv4_address(const char *key, char *retv, int inlen,
return fulllen;
}

static int get_config_net_veth_ipv4_route(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
int len;
size_t listlen;
char buf[INET_ADDRSTRLEN];
struct lxc_list *it;
int fulllen = 0;
struct lxc_netdev *netdev = data;

if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);

if (!netdev)
return minus_one_set_errno(EINVAL);

if (netdev->type != LXC_NET_VETH)
return 0;

listlen = lxc_list_len(&netdev->priv.veth_attr.ipv4_routes);

lxc_list_for_each(it, &netdev->priv.veth_attr.ipv4_routes) {
struct lxc_inetdev *i = it->elem;
inet_ntop(AF_INET, &i->addr, buf, sizeof(buf));
strprint(retv, inlen, "%s/%u%s", buf, i->prefix,
(listlen-- > 1) ? "\n" : "");
}

return fulllen;
}

static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
Expand Down Expand Up @@ -5330,6 +5531,39 @@ static int get_config_net_ipv6_address(const char *key, char *retv, int inlen,
return fulllen;
}

static int get_config_net_veth_ipv6_route(const char *key, char *retv, int inlen,
struct lxc_conf *c, void *data)
{
int len;
size_t listlen;
char buf[INET6_ADDRSTRLEN];
struct lxc_list *it;
int fulllen = 0;
struct lxc_netdev *netdev = data;

if (!retv)
inlen = 0;
else
memset(retv, 0, inlen);

if (!netdev)
return minus_one_set_errno(EINVAL);

if (netdev->type != LXC_NET_VETH)
return 0;

listlen = lxc_list_len(&netdev->priv.veth_attr.ipv6_routes);

lxc_list_for_each(it, &netdev->priv.veth_attr.ipv6_routes) {
struct lxc_inet6dev *i = it->elem;
inet_ntop(AF_INET6, &i->addr, buf, sizeof(buf));
strprint(retv, inlen, "%s/%u%s", buf, i->prefix,
(listlen-- > 1) ? "\n" : "");
}

return fulllen;
}

int lxc_list_config_items(char *retv, int inlen)
{
size_t i;
Expand Down Expand Up @@ -5463,6 +5697,8 @@ int lxc_list_net(struct lxc_conf *c, const char *key, char *retv, int inlen)
switch (netdev->type) {
case LXC_NET_VETH:
strprint(retv, inlen, "veth.pair\n");
strprint(retv, inlen, "veth.ipv4.route\n");
strprint(retv, inlen, "veth.ipv6.route\n");
break;
case LXC_NET_MACVLAN:
strprint(retv, inlen, "macvlan.mode\n");
Expand Down

0 comments on commit d4a7da4

Please sign in to comment.