]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: tunnel: support external mode
authorYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 1 Feb 2022 23:56:14 +0000 (08:56 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 3 Feb 2022 02:12:01 +0000 (11:12 +0900)
Closes #22352.

man/systemd.netdev.xml
src/network/netdev/netdev-gperf.gperf
src/network/netdev/tunnel.c
src/network/netdev/tunnel.h
test/fuzz/fuzz-netdev-parser/directives.netdev

index ff0bdee51fb3e37512ce7cc41686df1287954b5d..0ad0864da0f0ee966e034b5373c846139ef200f7 100644 (file)
     the following keys:</para>
 
     <variablelist class='network-directives'>
+      <varlistentry>
+        <term><varname>External=</varname></term>
+        <listitem>
+          <para>Takes a boolean value. When true, then the tunnel is externally controlled, which is
+          also known as collect metadata mode, and most settings below like <varname>Local=</varname>
+          or <varname>Remote=</varname> are ignored. This implies <varname>Independent=</varname>.
+          Defaults to false.</para>
+        </listitem>
+      </varlistentry>
       <varlistentry>
         <term><varname>Local=</varname></term>
         <listitem>
index a993e25867911f7627f424009525d989385d2244..eadafbddb84660bff0dc842b7b20c8963c501f99 100644 (file)
@@ -91,6 +91,7 @@ Tunnel.IPv6RapidDeploymentPrefix,         config_parse_6rd_prefix,
 Tunnel.ERSPANIndex,                       config_parse_uint32,                       0,                             offsetof(Tunnel, erspan_index)
 Tunnel.SerializeTunneledPackets,          config_parse_tristate,                     0,                             offsetof(Tunnel, gre_erspan_sequence)
 Tunnel.ISATAP,                            config_parse_tristate,                     0,                             offsetof(Tunnel, isatap)
+Tunnel.External,                          config_parse_bool,                         0,                             offsetof(Tunnel, external)
 FooOverUDP.Protocol,                      config_parse_ip_protocol,                  0,                             offsetof(FouTunnel, fou_protocol)
 FooOverUDP.Encapsulation,                 config_parse_fou_encap_type,               0,                             offsetof(FouTunnel, fou_encap_type)
 FooOverUDP.Port,                          config_parse_ip_port,                      0,                             offsetof(FouTunnel, port)
index 336ff3c8294805924b5123f0ff8f0dc324661095..bb6e4f75869f434611d3292bdacbd623268adcb5 100644 (file)
@@ -213,6 +213,15 @@ static int netdev_ipip_sit_fill_message_create(NetDev *netdev, Link *link, sd_ne
 
         assert(t);
 
+        if (t->external) {
+                r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
+                if (r < 0)
+                        return r;
+
+                /* If external mode is enabled, then the following settings should not be appended. */
+                return 0;
+        }
+
         if (link || t->assign_to_loopback) {
                 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
                 if (r < 0)
@@ -309,6 +318,15 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
 
         assert(t);
 
+        if (t->external) {
+                r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
+                if (r < 0)
+                        return r;
+
+                /* If external mode is enabled, then the following settings should not be appended. */
+                return 0;
+        }
+
         if (link || t->assign_to_loopback) {
                 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
                 if (r < 0)
@@ -421,6 +439,15 @@ static int netdev_ip6gre_fill_message_create(NetDev *netdev, Link *link, sd_netl
 
         assert(t);
 
+        if (t->external) {
+                r = sd_netlink_message_append_flag(m, IFLA_GRE_COLLECT_METADATA);
+                if (r < 0)
+                        return r;
+
+                /* If external mode is enabled, then the following settings should not be appended. */
+                return 0;
+        }
+
         if (link || t->assign_to_loopback) {
                 r = sd_netlink_message_append_u32(m, IFLA_GRE_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
                 if (r < 0)
@@ -553,6 +580,32 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
 
         assert(t);
 
+        switch (t->ip6tnl_mode) {
+        case NETDEV_IP6_TNL_MODE_IP6IP6:
+                proto = IPPROTO_IPV6;
+                break;
+        case NETDEV_IP6_TNL_MODE_IPIP6:
+                proto = IPPROTO_IPIP;
+                break;
+        case NETDEV_IP6_TNL_MODE_ANYIP6:
+        default:
+                proto = 0;
+                break;
+        }
+
+        r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
+        if (r < 0)
+                return r;
+
+        if (t->external) {
+                r = sd_netlink_message_append_flag(m, IFLA_IPTUN_COLLECT_METADATA);
+                if (r < 0)
+                        return r;
+
+                /* If external mode is enabled, then the following settings should not be appended. */
+                return 0;
+        }
+
         if (link || t->assign_to_loopback) {
                 r = sd_netlink_message_append_u32(m, IFLA_IPTUN_LINK, link ? link->ifindex : LOOPBACK_IFINDEX);
                 if (r < 0)
@@ -597,23 +650,6 @@ static int netdev_ip6tnl_fill_message_create(NetDev *netdev, Link *link, sd_netl
                         return r;
         }
 
-        switch (t->ip6tnl_mode) {
-        case NETDEV_IP6_TNL_MODE_IP6IP6:
-                proto = IPPROTO_IPV6;
-                break;
-        case NETDEV_IP6_TNL_MODE_IPIP6:
-                proto = IPPROTO_IPIP;
-                break;
-        case NETDEV_IP6_TNL_MODE_ANYIP6:
-        default:
-                proto = 0;
-                break;
-        }
-
-        r = sd_netlink_message_append_u8(m, IFLA_IPTUN_PROTO, proto);
-        if (r < 0)
-                return r;
-
         return 0;
 }
 
@@ -640,6 +676,23 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
 
         assert(t);
 
+        if (netdev->kind == NETDEV_KIND_IP6TNL &&
+            t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "ip6tnl without mode configured in %s. Ignoring", filename);
+
+        if (t->external) {
+                if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_VTI6))
+                        log_netdev_debug(netdev, "vti/vti6 tunnel do not support external mode, ignoring.");
+                else {
+                        /* tunnel with external mode does not require underlying interface. */
+                        t->independent = true;
+
+                        /* tunnel with external mode does not require any settings checked below. */
+                        return 0;
+                }
+        }
+
         if (IN_SET(netdev->kind, NETDEV_KIND_VTI, NETDEV_KIND_IPIP, NETDEV_KIND_SIT, NETDEV_KIND_GRE) &&
             !IN_SET(t->family, AF_UNSPEC, AF_INET))
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
@@ -660,11 +713,6 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                               "ip6gretap tunnel without a remote IPv6 address configured in %s. Ignoring", filename);
 
-        if (netdev->kind == NETDEV_KIND_IP6TNL &&
-            t->ip6tnl_mode == _NETDEV_IP6_TNL_MODE_INVALID)
-                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
-                                              "ip6tnl without mode configured in %s. Ignoring", filename);
-
         if (t->fou_tunnel && t->fou_destination_port <= 0)
                 return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
                                               "FooOverUDP missing port configured in %s. Ignoring", filename);
index 4d42ff9a154ccffcee8a6f702548f40b0c64c4d6..e25dfb215a0ffde9aaa7ffaaca11885b8569fa29 100644 (file)
@@ -55,6 +55,7 @@ typedef struct Tunnel {
         bool independent;
         bool fou_tunnel;
         bool assign_to_loopback;
+        bool external; /* a.k.a collect metadata mode */
 
         uint16_t encap_src_port;
         uint16_t fou_destination_port;
index f5fa2418feeb25b0bad0c8c6233e70077972e9b3..584c1c21361f8a160f17491647ee02fd844a053d 100644 (file)
@@ -95,6 +95,7 @@ IPv6RapidDeploymentPrefix=
 ERSPANIndex=
 SerializeTunneledPackets=
 ISATAP=
+External=
 [VXLAN]
 UDP6ZeroChecksumRx=
 ARPProxy=