mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-25 20:25:27 +00:00
network: Adds support host side veth device static routes
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>
This commit is contained in:
parent
41cd8a8d8c
commit
d4a7da4632
@ -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.
|
||||
|
@ -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>
|
||||
@ -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>
|
||||
@ -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.)
|
||||
|
||||
@ -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>
|
||||
@ -1708,7 +1714,7 @@ 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.
|
||||
@ -1716,7 +1722,7 @@ dev/null proc/kcore none bind,relative 0 0
|
||||
<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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
@ -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, },
|
||||
@ -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,
|
||||
@ -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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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)
|
||||
{
|
||||
@ -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;
|
||||
@ -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");
|
||||
|
@ -317,7 +317,7 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
|
||||
TRACE("type: none");
|
||||
break;
|
||||
default:
|
||||
ERROR("invalid network type %d", netdev->type);
|
||||
ERROR("Invalid network type %d", netdev->type);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -374,6 +374,28 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
|
||||
sizeof(bufinet6));
|
||||
TRACE("ipv6 addr: %s", bufinet6);
|
||||
}
|
||||
|
||||
if (netdev->type == LXC_NET_VETH) {
|
||||
lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) {
|
||||
inet4dev = cur->elem;
|
||||
if (!inet_ntop(AF_INET, &inet4dev->addr, bufinet4, sizeof(bufinet4))) {
|
||||
ERROR("Invalid ipv4 veth route");
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("ipv4 veth route: %s/%u", bufinet4, inet4dev->prefix);
|
||||
}
|
||||
|
||||
lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) {
|
||||
inet6dev = cur->elem;
|
||||
if (!inet_ntop(AF_INET6, &inet6dev->addr, bufinet6, sizeof(bufinet6))) {
|
||||
ERROR("Invalid ipv6 veth route");
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("ipv6 veth route: %s/%u", bufinet6, inet6dev->prefix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -401,6 +423,20 @@ static void lxc_free_netdev(struct lxc_netdev *netdev)
|
||||
free(cur);
|
||||
}
|
||||
|
||||
if (netdev->type == LXC_NET_VETH) {
|
||||
lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv4_routes, next) {
|
||||
lxc_list_del(cur);
|
||||
free(cur->elem);
|
||||
free(cur);
|
||||
}
|
||||
|
||||
lxc_list_for_each_safe(cur, &netdev->priv.veth_attr.ipv6_routes, next) {
|
||||
lxc_list_del(cur);
|
||||
free(cur->elem);
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
|
||||
free(netdev);
|
||||
}
|
||||
|
||||
|
@ -69,6 +69,44 @@ lxc_log_define(network, lxc);
|
||||
|
||||
typedef int (*instantiate_cb)(struct lxc_handler *, struct lxc_netdev *);
|
||||
|
||||
static int lxc_setup_ipv4_routes(struct lxc_list *ip, int ifindex)
|
||||
{
|
||||
struct lxc_list *iterator;
|
||||
int err;
|
||||
|
||||
lxc_list_for_each(iterator, ip) {
|
||||
struct lxc_inetdev *inetdev = iterator->elem;
|
||||
|
||||
err = lxc_ipv4_dest_add(ifindex, &inetdev->addr, inetdev->prefix);
|
||||
if (err) {
|
||||
SYSERROR("Failed to setup ipv4 route for network device "
|
||||
"with ifindex %d", ifindex);
|
||||
return minus_one_set_errno(-err);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lxc_setup_ipv6_routes(struct lxc_list *ip, int ifindex)
|
||||
{
|
||||
struct lxc_list *iterator;
|
||||
int err;
|
||||
|
||||
lxc_list_for_each(iterator, ip) {
|
||||
struct lxc_inet6dev *inet6dev = iterator->elem;
|
||||
|
||||
err = lxc_ipv6_dest_add(ifindex, &inet6dev->addr, inet6dev->prefix);
|
||||
if (err) {
|
||||
SYSERROR("Failed to setup ipv6 route for network device "
|
||||
"with ifindex %d", ifindex);
|
||||
return minus_one_set_errno(-err);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netdev)
|
||||
{
|
||||
int bridge_index, err;
|
||||
@ -183,6 +221,18 @@ static int instantiate_veth(struct lxc_handler *handler, struct lxc_netdev *netd
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
/* setup ipv4 routes on the host interface */
|
||||
if (lxc_setup_ipv4_routes(&netdev->priv.veth_attr.ipv4_routes, netdev->priv.veth_attr.ifindex)) {
|
||||
ERROR("Failed to setup ipv4 routes for network device \"%s\"", veth1);
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
/* setup ipv6 routes on the host interface */
|
||||
if (lxc_setup_ipv6_routes(&netdev->priv.veth_attr.ipv6_routes, netdev->priv.veth_attr.ifindex)) {
|
||||
ERROR("Failed to setup ipv6 routes for network device \"%s\"", veth1);
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
if (netdev->upscript) {
|
||||
char *argv[] = {
|
||||
"veth",
|
||||
@ -1780,7 +1830,7 @@ int lxc_ipv6_gateway_add(int ifindex, struct in6_addr *gw)
|
||||
return ip_gateway_add(AF_INET6, ifindex, gw);
|
||||
}
|
||||
|
||||
static int ip_route_dest_add(int family, int ifindex, void *dest)
|
||||
static int ip_route_dest_add(int family, int ifindex, void *dest, unsigned int netmask)
|
||||
{
|
||||
int addrlen, err;
|
||||
struct nl_handler nlh;
|
||||
@ -1815,7 +1865,7 @@ static int ip_route_dest_add(int family, int ifindex, void *dest)
|
||||
rt->rtm_scope = RT_SCOPE_LINK;
|
||||
rt->rtm_protocol = RTPROT_BOOT;
|
||||
rt->rtm_type = RTN_UNICAST;
|
||||
rt->rtm_dst_len = addrlen * 8;
|
||||
rt->rtm_dst_len = netmask;
|
||||
|
||||
err = -EINVAL;
|
||||
if (nla_put_buffer(nlmsg, RTA_DST, dest, addrlen))
|
||||
@ -1830,14 +1880,14 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest)
|
||||
int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest, unsigned int netmask)
|
||||
{
|
||||
return ip_route_dest_add(AF_INET, ifindex, dest);
|
||||
return ip_route_dest_add(AF_INET, ifindex, dest, netmask);
|
||||
}
|
||||
|
||||
int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest)
|
||||
int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest, unsigned int netmask)
|
||||
{
|
||||
return ip_route_dest_add(AF_INET6, ifindex, dest);
|
||||
return ip_route_dest_add(AF_INET6, ifindex, dest, netmask);
|
||||
}
|
||||
|
||||
bool is_ovs_bridge(const char *bridge)
|
||||
@ -2807,7 +2857,7 @@ static int setup_ipv4_addr(struct lxc_list *ip, int ifindex)
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv4 address for network device "
|
||||
"with eifindex %d", ifindex);
|
||||
"with ifindex %d", ifindex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -2829,7 +2879,7 @@ static int setup_ipv6_addr(struct lxc_list *ip, int ifindex)
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv6 address for network device "
|
||||
"with eifindex %d", ifindex);
|
||||
"with ifindex %d", ifindex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -2988,7 +3038,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
|
||||
|
||||
err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
|
||||
if (err) {
|
||||
err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway);
|
||||
err = lxc_ipv4_dest_add(netdev->ifindex, netdev->ipv4_gateway, 32);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to add ipv4 dest for network device \"%s\"",
|
||||
@ -3027,7 +3077,7 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
|
||||
|
||||
err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
|
||||
if (err) {
|
||||
err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway);
|
||||
err = lxc_ipv6_dest_add(netdev->ifindex, netdev->ipv6_gateway, 128);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to add ipv6 dest for network device \"%s\"",
|
||||
|
@ -95,6 +95,8 @@ struct ifla_veth {
|
||||
char pair[IFNAMSIZ];
|
||||
char veth1[IFNAMSIZ];
|
||||
int ifindex;
|
||||
struct lxc_list ipv4_routes;
|
||||
struct lxc_list ipv6_routes;
|
||||
};
|
||||
|
||||
struct ifla_vlan {
|
||||
@ -221,8 +223,8 @@ extern int lxc_ipv4_addr_get(int ifindex, struct in_addr **res);
|
||||
extern int lxc_ipv6_addr_get(int ifindex, struct in6_addr **res);
|
||||
|
||||
/* Set a destination route to an interface. */
|
||||
extern int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest);
|
||||
extern int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest);
|
||||
extern int lxc_ipv4_dest_add(int ifindex, struct in_addr *dest, unsigned int netmask);
|
||||
extern int lxc_ipv6_dest_add(int ifindex, struct in6_addr *dest, unsigned int netmask);
|
||||
|
||||
/* Set default route. */
|
||||
extern int lxc_ipv4_gateway_add(int ifindex, struct in_addr *gw);
|
||||
|
@ -134,6 +134,16 @@ static int set_and_clear_complete_netdev(struct lxc_container *c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.veth.ipv4.route", "192.0.2.1/32")) {
|
||||
lxc_error("%s\n", "lxc.net.1.veth.ipv4.route");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.veth.ipv6.route", "2001:db8::1/128")) {
|
||||
lxc_error("%s\n", "lxc.net.1.veth.ipv6.route");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.hwaddr",
|
||||
"52:54:00:80:7a:5d")) {
|
||||
lxc_error("%s\n", "lxc.net.1.hwaddr");
|
||||
@ -695,6 +705,16 @@ int main(int argc, char *argv[])
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv4.route", "192.0.2.1/32", tmpf, true, "veth")) {
|
||||
lxc_error("%s\n", "lxc.net.0.veth.ipv4.route");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load_network(c, "lxc.net.0.veth.ipv6.route", "2001:db8::1/128", tmpf, true, "veth")) {
|
||||
lxc_error("%s\n", "lxc.net.0.veth.ipv6.route");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.script.up", "/some/up/path", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.script.up");
|
||||
goto non_test_error;
|
||||
|
Loading…
Reference in New Issue
Block a user