mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-25 20:25:27 +00:00
network: Adds gateway device route mode
Adds ability to specify "dev" as the gateway value, which will cause a device route to be set as default gateway. Signed-off-by: tomponline <thomas.parrott@canonical.com>
This commit is contained in:
parent
5b94d538dd
commit
a2f9a6706d
@ -84,3 +84,10 @@ For IPv6 addresses it will check the following sysctl values and fail with an er
|
||||
net.ipv6.conf.[link].proxy_ndp=1
|
||||
net.ipv6.conf.[link].forwarding=1
|
||||
```
|
||||
|
||||
## network\_gateway\_device\_route
|
||||
|
||||
This introduces the ability to specify `lxc.net.[i].ipv4.gateway` and/or
|
||||
`lxc.net.[i].ipv6.gateway` with a value of `dev` which will cause the default gateway
|
||||
inside the container to be created as a device route without destination gateway IP needed.
|
||||
This is primarily intended for use with layer 3 networking devices, such as IPVLAN.
|
||||
|
@ -665,6 +665,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
the gateway. <option>auto</option> is only available when
|
||||
using the <option>veth</option>,
|
||||
<option>macvlan</option> and <option>ipvlan</option> network types.
|
||||
Can also have the special value of <option>dev</option>,
|
||||
which means to set the default gateway as a device route.
|
||||
This is primarily for use with layer 3 network modes, such as IPVLAN.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@ -699,6 +702,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
the gateway. <option>auto</option> is only available when
|
||||
using the <option>veth</option>,
|
||||
<option>macvlan</option> and <option>ipvlan</option> network types.
|
||||
Can also have the special value of <option>dev</option>,
|
||||
which means to set the default gateway as a device route.
|
||||
This is primarily for use with layer 3 network modes, such as IPVLAN.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
@ -47,6 +47,7 @@ static char *api_extensions[] = {
|
||||
"network_veth_routes",
|
||||
"network_ipvlan",
|
||||
"network_l2proxy",
|
||||
"network_gateway_device_route",
|
||||
};
|
||||
|
||||
static size_t nr_api_extensions = sizeof(api_extensions) / sizeof(*api_extensions);
|
||||
|
@ -686,9 +686,13 @@ static int set_config_net_ipv4_gateway(const char *key, const char *value,
|
||||
|
||||
free(netdev->ipv4_gateway);
|
||||
|
||||
if (!strcmp(value, "auto")) {
|
||||
if (strcmp(value, "auto") == 0) {
|
||||
netdev->ipv4_gateway = NULL;
|
||||
netdev->ipv4_gateway_auto = true;
|
||||
} else if (strcmp(value, "dev") == 0) {
|
||||
netdev->ipv4_gateway = NULL;
|
||||
netdev->ipv4_gateway_auto = false;
|
||||
netdev->ipv4_gateway_dev = true;
|
||||
} else {
|
||||
int ret;
|
||||
struct in_addr *gw;
|
||||
@ -853,9 +857,13 @@ static int set_config_net_ipv6_gateway(const char *key, const char *value,
|
||||
|
||||
free(netdev->ipv6_gateway);
|
||||
|
||||
if (!strcmp(value, "auto")) {
|
||||
if (strcmp(value, "auto") == 0) {
|
||||
netdev->ipv6_gateway = NULL;
|
||||
netdev->ipv6_gateway_auto = true;
|
||||
} else if (strcmp(value, "dev") == 0) {
|
||||
netdev->ipv6_gateway = NULL;
|
||||
netdev->ipv6_gateway_auto = false;
|
||||
netdev->ipv6_gateway_dev = true;
|
||||
} else {
|
||||
int ret;
|
||||
struct in6_addr *gw;
|
||||
@ -5625,6 +5633,8 @@ static int get_config_net_ipv4_gateway(const char *key, char *retv, int inlen,
|
||||
|
||||
if (netdev->ipv4_gateway_auto) {
|
||||
strprint(retv, inlen, "auto");
|
||||
} else if (netdev->ipv4_gateway_dev) {
|
||||
strprint(retv, inlen, "dev");
|
||||
} else if (netdev->ipv4_gateway) {
|
||||
inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
|
||||
strprint(retv, inlen, "%s", buf);
|
||||
@ -5714,6 +5724,8 @@ static int get_config_net_ipv6_gateway(const char *key, char *retv, int inlen,
|
||||
|
||||
if (netdev->ipv6_gateway_auto) {
|
||||
strprint(retv, inlen, "auto");
|
||||
} else if (netdev->ipv6_gateway_dev) {
|
||||
strprint(retv, inlen, "dev");
|
||||
} else if (netdev->ipv6_gateway) {
|
||||
inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
|
||||
strprint(retv, inlen, "%s", buf);
|
||||
|
@ -361,6 +361,9 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
|
||||
TRACE("ipv4 gateway auto: %s",
|
||||
netdev->ipv4_gateway_auto ? "true" : "false");
|
||||
|
||||
TRACE("ipv4 gateway dev: %s",
|
||||
netdev->ipv4_gateway_dev ? "true" : "false");
|
||||
|
||||
if (netdev->ipv4_gateway) {
|
||||
inet_ntop(AF_INET, netdev->ipv4_gateway,
|
||||
bufinet4, sizeof(bufinet4));
|
||||
@ -377,6 +380,9 @@ void lxc_log_configured_netdevs(const struct lxc_conf *conf)
|
||||
TRACE("ipv6 gateway auto: %s",
|
||||
netdev->ipv6_gateway_auto ? "true" : "false");
|
||||
|
||||
TRACE("ipv6 gateway dev: %s",
|
||||
netdev->ipv6_gateway_dev ? "true" : "false");
|
||||
|
||||
if (netdev->ipv6_gateway) {
|
||||
inet_ntop(AF_INET6, netdev->ipv6_gateway,
|
||||
bufinet6, sizeof(bufinet6));
|
||||
|
@ -2063,8 +2063,12 @@ static int ip_gateway_add(int family, int ifindex, void *gw)
|
||||
rt->rtm_dst_len = 0;
|
||||
|
||||
err = -EINVAL;
|
||||
if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
|
||||
goto out;
|
||||
|
||||
/* If gateway address not supplied, then a device route will be created instead */
|
||||
if (gw != NULL) {
|
||||
if (nla_put_buffer(nlmsg, RTA_GATEWAY, gw, addrlen))
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Adding the interface index enables the use of link-local
|
||||
* addresses for the gateway.
|
||||
@ -3381,12 +3385,12 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
|
||||
}
|
||||
|
||||
/* We can only set up the default routes after bringing
|
||||
* up the interface, sine bringing up the interface adds
|
||||
* up the interface, since bringing up the interface adds
|
||||
* the link-local routes and we can't add a default
|
||||
* route if the gateway is not reachable. */
|
||||
|
||||
/* setup ipv4 gateway on the interface */
|
||||
if (netdev->ipv4_gateway) {
|
||||
if (netdev->ipv4_gateway || netdev->ipv4_gateway_dev) {
|
||||
if (!(netdev->flags & IFF_UP)) {
|
||||
ERROR("Cannot add ipv4 gateway for network device "
|
||||
"\"%s\" when not bringing up the interface", ifname);
|
||||
@ -3399,33 +3403,43 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
|
||||
if (err) {
|
||||
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\"",
|
||||
/* Setup device route if ipv4_gateway_dev is enabled */
|
||||
if (netdev->ipv4_gateway_dev) {
|
||||
err = lxc_ipv4_gateway_add(netdev->ifindex, NULL);
|
||||
if (err < 0) {
|
||||
SYSERROR("Failed to setup ipv4 gateway to network device \"%s\"",
|
||||
ifname);
|
||||
return minus_one_set_errno(-err);
|
||||
}
|
||||
|
||||
} else {
|
||||
err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
|
||||
ifname);
|
||||
|
||||
if (netdev->ipv4_gateway_auto) {
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
|
||||
ERROR("Tried to set autodetected ipv4 gateway \"%s\"", buf);
|
||||
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\"",
|
||||
ifname);
|
||||
}
|
||||
|
||||
err = lxc_ipv4_gateway_add(netdev->ifindex, netdev->ipv4_gateway);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv4 gateway for network device \"%s\"",
|
||||
ifname);
|
||||
|
||||
if (netdev->ipv4_gateway_auto) {
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET, netdev->ipv4_gateway, buf, sizeof(buf));
|
||||
ERROR("Tried to set autodetected ipv4 gateway \"%s\"", buf);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* setup ipv6 gateway on the interface */
|
||||
if (netdev->ipv6_gateway) {
|
||||
if (netdev->ipv6_gateway || netdev->ipv6_gateway_dev) {
|
||||
if (!(netdev->flags & IFF_UP)) {
|
||||
ERROR("Cannot add ipv6 gateway for network device "
|
||||
"\"%s\" when not bringing up the interface", ifname);
|
||||
@ -3438,29 +3452,39 @@ static int lxc_setup_netdev_in_child_namespaces(struct lxc_netdev *netdev)
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
|
||||
if (err) {
|
||||
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\"",
|
||||
/* Setup device route if ipv6_gateway_dev is enabled */
|
||||
if (netdev->ipv6_gateway_dev) {
|
||||
err = lxc_ipv6_gateway_add(netdev->ifindex, NULL);
|
||||
if (err < 0) {
|
||||
SYSERROR("Failed to setup ipv6 gateway to network device \"%s\"",
|
||||
ifname);
|
||||
return minus_one_set_errno(-err);
|
||||
}
|
||||
|
||||
} else {
|
||||
err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
|
||||
ifname);
|
||||
|
||||
if (netdev->ipv6_gateway_auto) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
|
||||
ERROR("Tried to set autodetected ipv6 "
|
||||
"gateway for network device "
|
||||
"\"%s\"", buf);
|
||||
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\"",
|
||||
ifname);
|
||||
}
|
||||
|
||||
err = lxc_ipv6_gateway_add(netdev->ifindex, netdev->ipv6_gateway);
|
||||
if (err) {
|
||||
errno = -err;
|
||||
SYSERROR("Failed to setup ipv6 gateway for network device \"%s\"",
|
||||
ifname);
|
||||
|
||||
if (netdev->ipv6_gateway_auto) {
|
||||
char buf[INET6_ADDRSTRLEN];
|
||||
inet_ntop(AF_INET6, netdev->ipv6_gateway, buf, sizeof(buf));
|
||||
ERROR("Tried to set autodetected ipv6 "
|
||||
"gateway for network device "
|
||||
"\"%s\"", buf);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -156,9 +156,11 @@ union netdev_p {
|
||||
* @ipv6 : a list of ipv6 addresses to be set on the network device
|
||||
* @ipv4_gateway_auto : whether the ipv4 gateway is to be automatically gathered
|
||||
* from the associated @link
|
||||
* @ipv4_gateway_dev : whether the ipv4 gateway is to be set as a device route
|
||||
* @ipv4_gateway : ipv4 gateway
|
||||
* @ipv6_gateway_auto : whether the ipv6 gateway is to be automatically gathered
|
||||
* from the associated @link
|
||||
* @ipv6_gateway_dev : whether the ipv6 gateway is to be set as a device route
|
||||
* @ipv6_gateway : ipv6 gateway
|
||||
* @upscript : a script filename to be executed during interface
|
||||
* configuration
|
||||
@ -179,8 +181,10 @@ struct lxc_netdev {
|
||||
struct lxc_list ipv4;
|
||||
struct lxc_list ipv6;
|
||||
bool ipv4_gateway_auto;
|
||||
bool ipv4_gateway_dev;
|
||||
struct in_addr *ipv4_gateway;
|
||||
bool ipv6_gateway_auto;
|
||||
bool ipv6_gateway_dev;
|
||||
struct in6_addr *ipv6_gateway;
|
||||
char *upscript;
|
||||
char *downscript;
|
||||
|
@ -108,6 +108,16 @@ static int set_and_clear_complete_netdev(struct lxc_container *c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.ipv4.gateway", "auto")) {
|
||||
lxc_error("%s\n", "lxc.net.1.ipv4.gateway");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.ipv4.gateway", "dev")) {
|
||||
lxc_error("%s\n", "lxc.net.1.ipv4.gateway");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.ipv6.address",
|
||||
"2003:db8:1:0:214:1234:fe0b:3596/64")) {
|
||||
lxc_error("%s\n", "lxc.net.1.ipv6.address");
|
||||
@ -120,6 +130,16 @@ static int set_and_clear_complete_netdev(struct lxc_container *c)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.ipv6.gateway", "auto")) {
|
||||
lxc_error("%s\n", "lxc.net.1.ipv6.gateway");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.ipv6.gateway", "dev")) {
|
||||
lxc_error("%s\n", "lxc.net.1.ipv6.gateway");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!c->set_config_item(c, "lxc.net.1.flags", "up")) {
|
||||
lxc_error("%s\n", "lxc.net.1.flags");
|
||||
return -1;
|
||||
@ -781,11 +801,31 @@ int main(int argc, char *argv[])
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv4.gateway", "auto", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv4.gateway");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv4.gateway", "dev", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv4.gateway");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv6.gateway", "2003:db8:1::1", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv6.gateway");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv6.gateway", "auto", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv6.gateway");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv6.gateway", "dev", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv6.gateway");
|
||||
goto non_test_error;
|
||||
}
|
||||
|
||||
if (set_get_compare_clear_save_load(c, "lxc.net.0.ipv4.address", "10.0.2.3/24", tmpf, true)) {
|
||||
lxc_error("%s\n", "lxc.net.0.ipv4.address");
|
||||
goto non_test_error;
|
||||
|
Loading…
Reference in New Issue
Block a user