<varlistentry>
<term><varname>VNI=</varname></term>
<listitem>
- <para>The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1…16777215.</para>
+ <para>The VXLAN Network Identifier (or VXLAN Segment ID). Takes a number in the range 1…16777215.
+ Ignored if <varname>External=</varname> is set to true.</para>
<xi:include href="version-info.xml" xpointer="v243"/>
</listitem>
<xi:include href="version-info.xml" xpointer="v247"/>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>External=</varname></term>
+ <listitem>
+ <para>Takes a boolean. When true, the vxlan interface is externally controlled, for example by an
+ EVPN control plane. Defaults to false.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><varname>VNIFilter=</varname></term>
+ <listitem>
+ <para>Takes a boolean. When true, the interface is capable of filtering VNI filtering.
+ Ignored if <varname>External=</varname> is set to false. Defaults to false.</para>
+
+ <xi:include href="version-info.xml" xpointer="v258"/>
+ </listitem>
+ </varlistentry>
</variablelist>
</refsect1>
[IFLA_VXLAN_GPE] = BUILD_POLICY(FLAG),
[IFLA_VXLAN_TTL_INHERIT] = BUILD_POLICY(FLAG),
[IFLA_VXLAN_DF] = BUILD_POLICY(U8),
+ [IFLA_VXLAN_VNIFILTER] = BUILD_POLICY(U8),
};
static const NLAPolicy rtnl_link_info_data_xfrm_policies[] = {
VXLAN.FlowLabel, config_parse_flow_label, 0, 0
VXLAN.IPDoNotFragment, config_parse_df, 0, offsetof(VxLan, df)
VXLAN.Independent, config_parse_bool, 0, offsetof(VxLan, independent)
+VXLAN.External, config_parse_bool, 0, offsetof(VxLan, external)
+VXLAN.VNIFilter, config_parse_bool, 0, offsetof(VxLan, vnifilter)
GENEVE.Id, config_parse_geneve_vni, 0, offsetof(Geneve, id)
GENEVE.Remote, config_parse_geneve_address, 0, offsetof(Geneve, remote)
GENEVE.TOS, config_parse_uint8, 0, offsetof(Geneve, tos)
/* The properties below cannot be updated, and the kernel refuses the whole request if one of the
* following attributes is set for an existing interface. */
- if (v->vni <= VXLAN_VID_MAX) {
+ if (!v->external && v->vni <= VXLAN_VID_MAX) {
r = sd_netlink_message_append_u32(m, IFLA_VXLAN_ID, v->vni);
if (r < 0)
return r;
return r;
}
+ r = sd_netlink_message_append_u8(m, IFLA_VXLAN_COLLECT_METADATA, v->external);
+ if (r < 0)
+ return r;
+
+ if (v->external) {
+ r = sd_netlink_message_append_u8(m, IFLA_VXLAN_VNIFILTER, v->vnifilter);
+ if (r < 0)
+ return r;
+ }
+
return 0;
}
VxLan *v = VXLAN(netdev);
- if (v->vni > VXLAN_VID_MAX)
- return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
- "%s: VXLAN without valid VNI (or VXLAN Segment ID) configured. Ignoring.",
- filename);
-
if (v->ttl > 255)
return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
"%s: VXLAN TTL must be <= 255. Ignoring.",
"The local address cannot be '%s' when Independent= is enabled, ignoring.",
strna(netdev_local_address_type_to_string(v->local_type)));
+ if (v->external) {
+ if (v->vni <= VXLAN_VID_MAX)
+ log_netdev_warning(netdev, "VNI= is set while External= is enabled. VNI= setting will be ignored.");
+ } else {
+ if (v->vnifilter)
+ log_netdev_warning(netdev, "VNIFilter= is enabled while External= is disabled. VNIFilter= setting will be ignored.");
+ if (v->vni > VXLAN_VID_MAX)
+ return log_netdev_warning_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+ "%s: VXLAN without valid VNI (or VXLAN Segment ID) configured. Ignoring.",
+ filename);
+ }
+
return 0;
}
v->udpcsum = false;
v->udp6zerocsumtx = false;
v->udp6zerocsumrx = false;
+ v->external = false;
+ v->vnifilter = false;
}
const NetDevVTable vxlan_vtable = {
bool generic_protocol_extension;
bool inherit;
bool independent;
+ bool external; /* a.k.a collect metadata mode */
+ bool vnifilter;
struct ifla_vxlan_port_range port_range;
};
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[NetDev]
+Name=vxlan-external
+Kind=vxlan
+
+[VXLAN]
+External=true
+VNIFilter=true
+L2MissNotification=true
+L3MissNotification=true
+RouteShortCircuit=true
+UDPChecksum=true
+UDP6ZeroChecksumTx=true
+UDP6ZeroChecksumRx=true
+RemoteChecksumTx=true
+RemoteChecksumRx=true
+GroupPolicyExtension=true
+Independent=true
+DestinationPort=4444
--- /dev/null
+# SPDX-License-Identifier: LGPL-2.1-or-later
+[Match]
+Name=vxlan-external
+
+[Network]
+Address=::/64
'25-vxlan-ipv6.netdev', '25-vxlan-ipv6.network',
'25-vxlan-independent.netdev', '26-netdev-link-local-addressing-yes.network',
'25-veth.netdev', '25-vxlan-veth99.network', '25-ipv6-prefix.network',
- '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network')
+ '25-vxlan-local-slaac.netdev', '25-vxlan-local-slaac.network',
+ '25-vxlan-external.netdev', '25-vxlan-external.network')
start_networkd()
self.wait_online('test1:degraded', 'veth99:routable', 'veth-peer:degraded',
- 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded')
+ 'vxlan99:degraded', 'vxlan98:degraded', 'vxlan97:degraded', 'vxlan-slaac:degraded',
+ 'vxlan-external:degraded')
self.networkctl_check_unit('test1', '11-dummy', '25-vxlan-test1')
self.networkctl_check_unit('veth99', '25-veth', '25-vxlan-veth99')
self.networkctl_check_unit('veth-peer', '25-veth', '25-ipv6-prefix')
self.networkctl_check_unit('vxlan98', '25-vxlan-independent', '26-netdev-link-local-addressing-yes')
self.networkctl_check_unit('vxlan97', '25-vxlan-ipv6', '25-vxlan-ipv6')
self.networkctl_check_unit('vxlan-slaac', '25-vxlan-local-slaac', '25-vxlan-local-slaac')
+ self.networkctl_check_unit('vxlan-external', '25-vxlan-external', '25-vxlan-external')
output = check_output('ip -d -d link show vxlan99')
print(output)
print(output)
self.assertIn('inet6 2002:da8:1:0:1034:56ff:fe78:9abc/64 scope global dynamic', output)
+ output = check_output('ip -d link show vxlan-external')
+ print(output)
+ self.assertIn('id 0 ', output)
+ self.assertIn('external', output)
+ self.assertIn('vnifilter', output)
+
@unittest.skipUnless(compare_kernel_version("6"), reason="Causes kernel panic on unpatched kernels: https://bugzilla.kernel.org/show_bug.cgi?id=208315")
def test_macsec(self):
copy_network_unit('25-macsec.netdev', '25-macsec.network', '25-macsec.key',