summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuca Boccassi <luca.boccassi@microsoft.com>2021-12-26 17:27:41 +0000
committerGitHub <noreply@github.com>2021-12-26 17:27:41 +0000
commit4ac8526215bbdf20466898128147841ba57908da (patch)
treee1358d849aaae574f009bd0222cc040c0fd79271
parentbfa6bd1be098adc4710e1819b9cd34d65b3855da (diff)
parent49ad8da7798248f2b604e937afb2727aa3c89454 (diff)
downloadsystemd-4ac8526215bbdf20466898128147841ba57908da.tar.gz
Merge pull request #21892 from yuwata/network-vxlan-automatic-local-address-selection
network: vxlan: automatic local address selection
-rw-r--r--man/systemd.netdev.xml6
-rw-r--r--src/network/netdev/vxlan.c98
-rw-r--r--src/network/netdev/vxlan.h4
-rw-r--r--test/test-network/conf/25-vxlan-local-slaac.netdev8
-rw-r--r--test/test-network/conf/25-vxlan-local-slaac.network7
-rw-r--r--test/test-network/conf/25-vxlan-veth99.network10
-rwxr-xr-xtest/test-network/systemd-networkd-tests.py21
7 files changed, 133 insertions, 21 deletions
diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index c26b60fb24..7d5c0ac729 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -573,7 +573,11 @@
<varlistentry>
<term><varname>Local=</varname></term>
<listitem>
- <para>Configures local IP address.</para>
+ <para>Configures local IP address. It must be an address on the underlying interface of the
+ VXLAN interface, or one of the special values <literal>ipv4_link_local</literal>,
+ <literal>ipv6_link_local</literal>, <literal>dhcp4</literal>, <literal>dhcp6</literal>, and
+ <literal>slaac</literal>. If one of the special values is specified, an address which matches
+ the corresponding type on the underlying interface will be used. Defaults to unset.</para>
</listitem>
</varlistentry>
<varlistentry>
diff --git a/src/network/netdev/vxlan.c b/src/network/netdev/vxlan.c
index 30b0855598..addeb907dd 100644
--- a/src/network/netdev/vxlan.c
+++ b/src/network/netdev/vxlan.c
@@ -22,9 +22,24 @@ static const char* const df_table[_NETDEV_VXLAN_DF_MAX] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(df, VxLanDF, NETDEV_VXLAN_DF_YES);
DEFINE_CONFIG_PARSE_ENUM(config_parse_df, df, VxLanDF, "Failed to parse VXLAN IPDoNotFragment= setting");
+static int vxlan_get_local_address(VxLan *v, Link *link, int *ret_family, union in_addr_union *ret_address) {
+ assert(v);
+
+ if (v->local_type < 0) {
+ if (ret_family)
+ *ret_family = v->local_family;
+ if (ret_address)
+ *ret_address = v->local;
+ return 0;
+ }
+
+ return link_get_local_address(link, v->local_type, v->local_family, ret_family, ret_address);
+}
+
static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netlink_message *m) {
+ union in_addr_union local;
+ int local_family, r;
VxLan *v;
- int r;
assert(netdev);
assert(m);
@@ -55,11 +70,15 @@ static int netdev_vxlan_fill_message_create(NetDev *netdev, Link *link, sd_netli
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_GROUP attribute: %m");
}
- if (in_addr_is_set(v->local_family, &v->local)) {
- if (v->local_family == AF_INET)
- r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_LOCAL, &v->local.in);
+ r = vxlan_get_local_address(v, link, &local_family, &local);
+ if (r < 0)
+ return log_netdev_error_errno(netdev, r, "Could not find local address: %m");
+
+ if (in_addr_is_set(local_family, &local)) {
+ if (local_family == AF_INET)
+ r = sd_netlink_message_append_in_addr(m, IFLA_VXLAN_LOCAL, &local.in);
else
- r = sd_netlink_message_append_in6_addr(m, IFLA_VXLAN_LOCAL6, &v->local.in6);
+ r = sd_netlink_message_append_in6_addr(m, IFLA_VXLAN_LOCAL6, &local.in6);
if (r < 0)
return log_netdev_error_errno(netdev, r, "Could not append IFLA_VXLAN_LOCAL attribute: %m");
}
@@ -190,16 +209,45 @@ int config_parse_vxlan_address(
VxLan *v = userdata;
union in_addr_union *addr = data, buffer;
- int r, f;
+ int *family, f, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
+ assert(userdata);
+
+ if (streq(lvalue, "Local"))
+ family = &v->local_family;
+ else if (streq(lvalue, "Remote"))
+ family = &v->remote_family;
+ else if (streq(lvalue, "Group"))
+ family = &v->group_family;
+ else
+ assert_not_reached();
+
+ if (isempty(rvalue)) {
+ *addr = IN_ADDR_NULL;
+ *family = AF_UNSPEC;
+ return 0;
+ }
+
+ if (streq(lvalue, "Local")) {
+ NetDevLocalAddressType t;
+
+ t = netdev_local_address_type_from_string(rvalue);
+ if (t >= 0) {
+ v->local = IN_ADDR_NULL;
+ v->local_family = AF_UNSPEC;
+ v->local_type = t;
+ return 0;
+ }
+ }
r = in_addr_from_string_auto(rvalue, &f, &buffer);
if (r < 0) {
- log_syntax(unit, LOG_WARNING, filename, line, r, "vxlan '%s' address is invalid, ignoring assignment: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, r,
+ "Failed to parse %s=, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
@@ -207,24 +255,22 @@ int config_parse_vxlan_address(
if (streq(lvalue, "Group")) {
if (r <= 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "vxlan %s invalid multicast address, ignoring assignment: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "%s= must be a multicast address, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
-
- v->group_family = f;
} else {
if (r > 0) {
- log_syntax(unit, LOG_WARNING, filename, line, 0, "vxlan %s cannot be a multicast address, ignoring assignment: %s", lvalue, rvalue);
+ log_syntax(unit, LOG_WARNING, filename, line, 0,
+ "%s= cannot be a multicast address, ignoring assignment: %s", lvalue, rvalue);
return 0;
}
-
- if (streq(lvalue, "Remote"))
- v->remote_family = f;
- else
- v->local_family = f;
}
+ if (streq(lvalue, "Local"))
+ v->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
*addr = buffer;
+ *family = f;
return 0;
}
@@ -369,9 +415,27 @@ static int netdev_vxlan_verify(NetDev *netdev, const char *filename) {
"%s: VXLAN both 'Group=' and 'Remote=' cannot be specified. Ignoring.",
filename);
+ if (v->independent && v->local_type >= 0)
+ return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+ "The local address cannot be '%s' when Independent= is enabled, ignoring.",
+ strna(netdev_local_address_type_to_string(v->local_type)));
+
return 0;
}
+static int netdev_vxlan_is_ready_to_create(NetDev *netdev, Link *link) {
+ VxLan *v;
+
+ assert(netdev);
+ assert(link);
+
+ v = VXLAN(netdev);
+
+ assert(v);
+
+ return vxlan_get_local_address(v, link, NULL, NULL) >= 0;
+}
+
static void vxlan_init(NetDev *netdev) {
VxLan *v;
@@ -381,6 +445,7 @@ static void vxlan_init(NetDev *netdev) {
assert(v);
+ v->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
v->vni = VXLAN_VID_MAX + 1;
v->df = _NETDEV_VXLAN_DF_INVALID;
v->learning = true;
@@ -395,6 +460,7 @@ const NetDevVTable vxlan_vtable = {
.sections = NETDEV_COMMON_SECTIONS "VXLAN\0",
.fill_message_create = netdev_vxlan_fill_message_create,
.create_type = NETDEV_CREATE_STACKED,
+ .is_ready_to_create = netdev_vxlan_is_ready_to_create,
.config_verify = netdev_vxlan_verify,
.iftype = ARPHRD_ETHER,
.generate_mac = true,
diff --git a/src/network/netdev/vxlan.h b/src/network/netdev/vxlan.h
index 12ef46ef9a..141ac4db4d 100644
--- a/src/network/netdev/vxlan.h
+++ b/src/network/netdev/vxlan.h
@@ -6,6 +6,7 @@ typedef struct VxLan VxLan;
#include <linux/if_link.h>
#include "in-addr-util.h"
+#include "netdev-util.h"
#include "netdev.h"
#define VXLAN_VID_MAX (1u << 24) - 1
@@ -30,8 +31,9 @@ struct VxLan {
VxLanDF df;
- union in_addr_union remote;
+ NetDevLocalAddressType local_type;
union in_addr_union local;
+ union in_addr_union remote;
union in_addr_union group;
unsigned tos;
diff --git a/test/test-network/conf/25-vxlan-local-slaac.netdev b/test/test-network/conf/25-vxlan-local-slaac.netdev
new file mode 100644
index 0000000000..43f5934d2a
--- /dev/null
+++ b/test/test-network/conf/25-vxlan-local-slaac.netdev
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[NetDev]
+Name=vxlan-slaac
+Kind=vxlan
+
+[VXLAN]
+VNI=4831584
+Local=slaac
diff --git a/test/test-network/conf/25-vxlan-local-slaac.network b/test/test-network/conf/25-vxlan-local-slaac.network
new file mode 100644
index 0000000000..4ea1eae875
--- /dev/null
+++ b/test/test-network/conf/25-vxlan-local-slaac.network
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=vxlan-slaac
+
+[Network]
+IPv6AcceptRA=no
+LinkLocalAddressing=yes
diff --git a/test/test-network/conf/25-vxlan-veth99.network b/test/test-network/conf/25-vxlan-veth99.network
new file mode 100644
index 0000000000..b67b746624
--- /dev/null
+++ b/test/test-network/conf/25-vxlan-veth99.network
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=veth99
+
+[Network]
+IPv6AcceptRA=yes
+VXLAN=vxlan-slaac
+
+[IPv6AcceptRA]
+PrefixAllowList=2002:da8:1::/64
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index d3c9fdad01..5613398757 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -934,6 +934,7 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'vtitun98',
'vtitun99',
'vxcan99',
+ 'vxlan-slaac',
'vxlan97',
'vxlan98',
'vxlan99',
@@ -1029,6 +1030,9 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
'25-vxcan.netdev',
'25-vxlan-independent.netdev',
'25-vxlan-ipv6.netdev',
+ '25-vxlan-local-slaac.netdev',
+ '25-vxlan-local-slaac.network',
+ '25-vxlan-veth99.network',
'25-vxlan.netdev',
'25-wireguard-23-peers.netdev',
'25-wireguard-23-peers.network',
@@ -1825,13 +1829,16 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertRegex(output, 'encap fou encap-sport auto encap-dport 55556')
def test_vxlan(self):
- copy_unit_to_networkd_unit_path('25-vxlan.netdev', 'vxlan.network',
+ copy_unit_to_networkd_unit_path('11-dummy.netdev', 'vxlan-test1.network',
+ '25-vxlan.netdev', 'vxlan.network',
'25-vxlan-ipv6.netdev', 'vxlan-ipv6.network',
'25-vxlan-independent.netdev', 'netdev-link-local-addressing-yes.network',
- '11-dummy.netdev', 'vxlan-test1.network')
+ '25-veth.netdev', '25-vxlan-veth99.network', 'ipv6-prefix.network',
+ '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
start_networkd()
- self.wait_online(['test1:degraded', 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded'])
+ self.wait_online(['test1:degraded', 'veth99:routable', 'veth-peer:degraded',
+ 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded'])
output = check_output('ip -d link show vxlan99')
print(output)
@@ -1864,6 +1871,14 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
self.assertIn('00:00:00:00:00:00 dst fe80::27c:16ff:fec0:6c74 via test1 self permanent', output)
self.assertIn('00:00:00:00:00:00 dst fe80::2a2:e4ff:fef9:2269 via test1 self permanent', output)
+ output = check_output('ip -d link show vxlan-slaac')
+ print(output)
+ self.assertIn('vxlan id 4831584 local 2002:da8:1:0:1034:56ff:fe78:9abc dev veth99', output)
+
+ output = check_output('ip -6 address show veth99')
+ print(output)
+ self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
+
def test_macsec(self):
copy_unit_to_networkd_unit_path('25-macsec.netdev', '25-macsec.network', '25-macsec.key',
'macsec.network', '12-dummy.netdev')