#5 network: backport external tunnel support (https://github.com/systemd/systemd/pull/22355)
Merged 3 years ago by daandemeyer. Opened 3 years ago by daandemeyer.
centos-sig-hyperscale/ daandemeyer/systemd external-backport  into  fb-v250.3

file modified
+9
@@ -1146,6 +1146,15 @@ 

  

      <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>

            <para>A static local address for tunneled packets. It must be an address on another interface of

@@ -66,6 +66,14 @@ 

          #define free(a) FreePool(a)

  #endif

  

+ /* This passes the argument through after (if asserts are enabled) checking that it is not null. */

+ #define ASSERT_PTR(expr)                        \

+         ({                                      \

+                 typeof(expr) _expr_ = (expr);   \

+                 assert(_expr_);                 \

+                 _expr_;                         \

+         })

+ 

  #if defined(static_assert)

  #define assert_cc(expr)                                                 \

          static_assert(expr, #expr)

@@ -77,9 +77,9 @@ 

  Tunnel.OutputKey,                         config_parse_tunnel_key,                   0,                             offsetof(Tunnel, okey)

  Tunnel.DiscoverPathMTU,                   config_parse_bool,                         0,                             offsetof(Tunnel, pmtudisc)

  Tunnel.Mode,                              config_parse_ip6tnl_mode,                  0,                             offsetof(Tunnel, ip6tnl_mode)

- Tunnel.IPv6FlowLabel,                     config_parse_ipv6_flowlabel,               0,                             offsetof(Tunnel, ipv6_flowlabel)

+ Tunnel.IPv6FlowLabel,                     config_parse_ipv6_flowlabel,               0,                             0

  Tunnel.CopyDSCP,                          config_parse_bool,                         0,                             offsetof(Tunnel, copy_dscp)

- Tunnel.EncapsulationLimit,                config_parse_encap_limit,                  0,                             offsetof(Tunnel, encap_limit)

+ Tunnel.EncapsulationLimit,                config_parse_encap_limit,                  0,                             0

  Tunnel.Independent,                       config_parse_bool,                         0,                             offsetof(Tunnel, independent)

  Tunnel.AssignToLoopback,                  config_parse_bool,                         0,                             offsetof(Tunnel, assign_to_loopback)

  Tunnel.AllowLocalRemote,                  config_parse_tristate,                     0,                             offsetof(Tunnel, allow_localremote)
@@ -91,6 +91,7 @@ 

  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)

file modified
+114 -72
@@ -182,6 +182,15 @@ 

  

          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)
@@ -273,6 +282,15 @@ 

  

          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)
@@ -380,6 +398,15 @@ 

  

          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)
@@ -502,6 +529,32 @@ 

  

          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)
@@ -532,34 +585,17 @@ 

          if (t->allow_localremote >= 0)

                  SET_FLAG(t->flags, IP6_TNL_F_ALLOW_LOCAL_REMOTE, t->allow_localremote);

  

+         r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);

+         if (r < 0)

+                 return r;

+ 

          if (t->encap_limit != 0) {

                  r = sd_netlink_message_append_u8(m, IFLA_IPTUN_ENCAP_LIMIT, t->encap_limit);

                  if (r < 0)

                          return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_ENCAP_LIMIT attribute: %m");

          }

  

-         r = sd_netlink_message_append_u32(m, IFLA_IPTUN_FLAGS, t->flags);

-         if (r < 0)

-                 return log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_FLAGS attribute: %m");

- 

-         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 log_netdev_error_errno(netdev, r, "Could not append IFLA_IPTUN_PROTO attribute: %m");

- 

-         return r;

+         return 0;

  }

  

  static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
@@ -572,6 +608,23 @@ 

  

          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),
@@ -592,11 +645,6 @@ 

                  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);
@@ -682,15 +730,12 @@ 

                  void *data,

                  void *userdata) {

  

+         uint32_t *dest = ASSERT_PTR(data), k;

          union in_addr_union buffer;

-         Tunnel *t = userdata;

-         uint32_t k;

          int r;

  

          assert(filename);

-         assert(lvalue);

          assert(rvalue);

-         assert(data);

  

          r = in_addr_from_string(AF_INET, rvalue, &buffer);

          if (r < 0) {
@@ -703,13 +748,7 @@ 

          } else

                  k = be32toh(buffer.in.s_addr);

  

-         if (streq(lvalue, "Key"))

-                 t->key = k;

-         else if (streq(lvalue, "InputKey"))

-                 t->ikey = k;

-         else

-                 t->okey = k;

- 

+         *dest = k;

          return 0;

  }

  
@@ -725,32 +764,33 @@ 

                  void *data,

                  void *userdata) {

  

-         IPv6FlowLabel *ipv6_flowlabel = data;

-         Tunnel *t = userdata;

-         int k = 0;

-         int r;

+         Tunnel *t = ASSERT_PTR(userdata);

+         int k, r;

  

          assert(filename);

-         assert(lvalue);

          assert(rvalue);

-         assert(ipv6_flowlabel);

  

          if (streq(rvalue, "inherit")) {

-                 *ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;

+                 t->ipv6_flowlabel = IP6_FLOWINFO_FLOWLABEL;

                  t->flags |= IP6_TNL_F_USE_ORIG_FLOWLABEL;

-         } else {

-                 r = config_parse_int(unit, filename, line, section, section_line, lvalue, ltype, rvalue, &k, userdata);

-                 if (r < 0)

-                         return r;

+                 return 0;

+         }

  

-                 if (k > 0xFFFFF)

-                         log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse IPv6 flowlabel option, ignoring: %s", rvalue);

-                 else {

-                         *ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;

-                         t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;

-                 }

+         r = safe_atoi(rvalue, &k);

+         if (r < 0) {

+                 log_syntax(unit, LOG_WARNING, filename, line, r,

+                            "Failed to parse tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue);

+                 return 0;

          }

  

+         if (k > 0xFFFFF) {

+                 log_syntax(unit, LOG_WARNING, filename, line, 0,

+                            "Invalid tunnel IPv6 flowlabel, ignoring assignment: %s", rvalue);

+                 return 0;

+         }

+ 

+         t->ipv6_flowlabel = htobe32(k) & IP6_FLOWINFO_FLOWLABEL;

+         t->flags &= ~IP6_TNL_F_USE_ORIG_FLOWLABEL;

          return 0;

  }

  
@@ -766,31 +806,33 @@ 

                  void *data,

                  void *userdata) {

  

-         Tunnel *t = userdata;

-         int k = 0;

-         int r;

+         Tunnel *t = ASSERT_PTR(userdata);

+         int k, r;

  

          assert(filename);

-         assert(lvalue);

          assert(rvalue);

  

-         if (streq(rvalue, "none"))

+         if (streq(rvalue, "none")) {

                  t->flags |= IP6_TNL_F_IGN_ENCAP_LIMIT;

-         else {

-                 r = safe_atoi(rvalue, &k);

-                 if (r < 0) {

-                         log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse Tunnel Encapsulation Limit option, ignoring: %s", rvalue);

-                         return 0;

-                 }

+                 t->encap_limit = 0;

+                 return 0;

+         }

  

-                 if (k > 255 || k < 0)

-                         log_syntax(unit, LOG_WARNING, filename, line, 0, "Invalid Tunnel Encapsulation value, ignoring: %d", k);

-                 else {

-                         t->encap_limit = k;

-                         t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;

-                 }

+         r = safe_atoi(rvalue, &k);

+         if (r < 0) {

+                 log_syntax(unit, LOG_WARNING, filename, line, r,

+                            "Failed to parse Tunnel Encapsulation Limit option, ignoring assignment: %s", rvalue);

+                 return 0;

+         }

+ 

+         if (k > 255 || k < 0) {

+                 log_syntax(unit, LOG_WARNING, filename, line, 0,

+                            "Invalid Tunnel Encapsulation value, ignoring assignment: %d", k);

+                 return 0;

          }

  

+         t->encap_limit = k;

+         t->flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT;

          return 0;

  }

  

@@ -53,6 +53,7 @@ 

          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;

@@ -95,6 +95,7 @@ 

  ERSPANIndex=

  SerializeTunneledPackets=

  ISATAP=

+ External=

  [VXLAN]

  UDP6ZeroChecksumRx=

  ARPProxy=

@@ -0,0 +1,8 @@ 

+ # SPDX-License-Identifier: LGPL-2.1-or-later

+ [NetDev]

+ Name=ip6tnl-external

+ Kind=ip6tnl

+ 

+ [Tunnel]

+ Mode=ip6ip6

+ External=yes

@@ -2,6 +2,7 @@ 

  [Match]

  Name=bareudp99

  Name=batadv99

+ Name=ip6tnl-external

  Name=ipvlan99

  Name=ipvtap99

  Name=macvlan99

@@ -904,6 +904,7 @@ 

          'ip6gretun97',

          'ip6gretun98',

          'ip6gretun99',

+         'ip6tnl-external',

          'ip6tnl97',

          'ip6tnl98',

          'ip6tnl99',
@@ -988,7 +989,7 @@ 

          '25-ip6gre-tunnel-local-any.netdev',

          '25-ip6gre-tunnel-remote-any.netdev',

          '25-ip6gre-tunnel.netdev',

-         '25-ip6tnl-tunnel-any-any.netdev',

+         '25-ip6tnl-tunnel-external.netdev',

          '25-ip6tnl-tunnel-local-any.netdev',

          '25-ip6tnl-tunnel-remote-any.netdev',

          '25-ip6tnl-tunnel.netdev',
@@ -1668,9 +1669,10 @@ 

          copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-ip6tnl.network',

                                          '25-ip6tnl-tunnel.netdev', '25-tunnel.network',

                                          '25-ip6tnl-tunnel-local-any.netdev', '25-tunnel-local-any.network',

-                                         '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network')

+                                         '25-ip6tnl-tunnel-remote-any.netdev', '25-tunnel-remote-any.network',

+                                         '25-ip6tnl-external.netdev', '26-netdev-link-local-addressing-yes.network')

          start_networkd()

-         self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'dummy98:degraded'])

+         self.wait_online(['ip6tnl99:routable', 'ip6tnl98:routable', 'ip6tnl97:routable', 'ip6tnl-external:degraded', 'dummy98:degraded'])

  

          output = check_output('ip -d link show ip6tnl99')

          print(output)
@@ -1681,6 +1683,10 @@ 

          output = check_output('ip -d link show ip6tnl97')

          print(output)

          self.assertRegex(output, 'ip6tnl ip6ip6 remote (any|::) local 2a00:ffde:4567:edde::4987 dev dummy98')

+         output = check_output('ip -d link show ip6tnl-external')

+         print(output)

+         self.assertIn('ip6tnl-external@NONE:', output)

+         self.assertIn('ip6tnl external ', output)

  

      def test_sit_tunnel(self):

          copy_unit_to_networkd_unit_path('12-dummy.netdev', '25-sit.network',

I had to add one new commit to backport ASSERT_PTR() since that was added as part of an unrelated networkctl change but not as a separate commit so I added a new commit for that.

I ran the systemd-networkd-tests.py NetworkdNetDevTests.test_ip6tnl_tunnel() test in mkosi to verify the backport didn't introduce any regressions.

rebased onto 694e2dc

3 years ago

Pull-Request has been merged by daandemeyer

3 years ago