Skip to content

Commit 1ae308a

Browse files
committed
network: tunnel: support external mode
Closes systemd#22352.
1 parent acd8abb commit 1ae308a

File tree

5 files changed

+82
-22
lines changed

5 files changed

+82
-22
lines changed

man/systemd.netdev.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,15 @@
11491149
the following keys:</para>
11501150

11511151
<variablelist class='network-directives'>
1152+
<varlistentry>
1153+
<term><varname>External=</varname></term>
1154+
<listitem>
1155+
<para>Takes a boolean value. When true, then the tunnel is externally controlled, which is
1156+
also known as collect metadata mode, and most settings below like <varname>Local=</varname>
1157+
or <varname>Remote=</varname> are ignored. This implies <varname>Independent=</varname>.
1158+
Defaults to false.</para>
1159+
</listitem>
1160+
</varlistentry>
11521161
<varlistentry>
11531162
<term><varname>Local=</varname></term>
11541163
<listitem>

src/network/netdev/netdev-gperf.gperf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ Tunnel.IPv6RapidDeploymentPrefix, config_parse_6rd_prefix,
9191
Tunnel.ERSPANIndex, config_parse_uint32, 0, offsetof(Tunnel, erspan_index)
9292
Tunnel.SerializeTunneledPackets, config_parse_tristate, 0, offsetof(Tunnel, gre_erspan_sequence)
9393
Tunnel.ISATAP, config_parse_tristate, 0, offsetof(Tunnel, isatap)
94+
Tunnel.External, config_parse_bool, 0, offsetof(Tunnel, external)
9495
FooOverUDP.Protocol, config_parse_ip_protocol, 0, offsetof(FouTunnel, fou_protocol)
9596
FooOverUDP.Encapsulation, config_parse_fou_encap_type, 0, offsetof(FouTunnel, fou_encap_type)
9697
FooOverUDP.Port, config_parse_ip_port, 0, offsetof(FouTunnel, port)

src/network/netdev/tunnel.c

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
213213

214214
assert(t);
215215

216+
if (t->external) {
217+
r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
218+
if (r < 0)
219+
return r;
220+
221+
/* If external mode is enabled, then the following settings should not be appended. */
222+
return 0;
223+
}
224+
216225
if (link || t->assign_to_loopback) {
217226
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
218227
if (r < 0)
@@ -309,6 +318,15 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
309318

310319
assert(t);
311320

321+
if (t->external) {
322+
r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
323+
if (r < 0)
324+
return r;
325+
326+
/* If external mode is enabled, then the following settings should not be appended. */
327+
return 0;
328+
}
329+
312330
if (link || t->assign_to_loopback) {
313331
r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
314332
if (r < 0)
@@ -421,6 +439,15 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
421439

422440
assert(t);
423441

442+
if (t->external) {
443+
r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
444+
if (r < 0)
445+
return r;
446+
447+
/* If external mode is enabled, then the following settings should not be appended. */
448+
return 0;
449+
}
450+
424451
if (link || t->assign_to_loopback) {
425452
r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
426453
if (r < 0)
@@ -553,6 +580,32 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
553580

554581
assert(t);
555582

583+
switch (t->ip6tnl_mode) {
584+
case NETDEV_IP6_TNL_MODE_IP6IP6:
585+
proto = IPPROTO_IPV6;
586+
break;
587+
case NETDEV_IP6_TNL_MODE_IPIP6:
588+
proto = IPPROTO_IPIP;
589+
break;
590+
case NETDEV_IP6_TNL_MODE_ANYIP6:
591+
default:
592+
proto = 0;
593+
break;
594+
}
595+
596+
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
597+
if (r < 0)
598+
return r;
599+
600+
if (t->external) {
601+
r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
602+
if (r < 0)
603+
return r;
604+
605+
/* If external mode is enabled, then the following settings should not be appended. */
606+
return 0;
607+
}
608+
556609
if (link || t->assign_to_loopback) {
557610
r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
558611
if (r < 0)
@@ -597,23 +650,6 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
597650
return r;
598651
}
599652

600-
switch (t->ip6tnl_mode) {
601-
case NETDEV_IP6_TNL_MODE_IP6IP6:
602-
proto = IPPROTO_IPV6;
603-
break;
604-
case NETDEV_IP6_TNL_MODE_IPIP6:
605-
proto = IPPROTO_IPIP;
606-
break;
607-
case NETDEV_IP6_TNL_MODE_ANYIP6:
608-
default:
609-
proto = 0;
610-
break;
611-
}
612-
613-
r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
614-
if (r < 0)
615-
return r;
616-
617653
return 0;
618654
}
619655

@@ -640,6 +676,23 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
640676

641677
assert(t);
642678

679+
if (netdev->kind == NETDEV_KIND_IP6TNL &&
680+
t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
681+
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
682+
"ip6tnl without mode configured in %s. Ignoring", filename);
683+
684+
if (t->external) {
685+
if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_VTI6))
686+
log_netdev_debug(netdev, "vti/vti6 tunnel do not support external mode, ignoring.");
687+
else {
688+
/* tunnel with external mode does not require underlying interface. */
689+
t->independent = true;
690+
691+
/* tunnel with external mode does not require any settings checked below. */
692+
return 0;
693+
}
694+
}
695+
643696
if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) &&
644697
!IN_SET(t->family, AF_UNSPEC, AF_INET))
645698
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
@@ -660,11 +713,6 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
660713
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
661714
"ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename);
662715

663-
if (netdev->kind == NETDEV_KIND_IP6TNL &&
664-
t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
665-
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
666-
"ip6tnl without mode configured in %s. Ignoring", filename);
667-
668716
if (t->fou_tunnel && t->fou_destination_port <= 0)
669717
return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
670718
"FooOverUDP missing port configured in %s. Ignoring", filename);

src/network/netdev/tunnel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ typedef struct Tunnel {
5555
bool independent;
5656
bool fou_tunnel;
5757
bool assign_to_loopback;
58+
bool external; /* a.k.a collect metadata mode */
5859

5960
uint16_t encap_src_port;
6061
uint16_t fou_destination_port;

test/fuzz/fuzz-netdev-parser/directives.netdev

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ IPv6RapidDeploymentPrefix=
9595
ERSPANIndex=
9696
SerializeTunneledPackets=
9797
ISATAP=
98+
External=
9899
[VXLAN]
99100
UDP6ZeroChecksumRx=
100101
ARPProxy=

0 commit comments

Comments
 (0)