]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network: Add `IgnoreDdontFragment=` option for Fragmentation control (#28131)
authorYuxiang Zhu <vfreex+github@gmail.com>
Thu, 29 Jun 2023 10:11:52 +0000 (18:11 +0800)
committerGitHub <noreply@github.com>
Thu, 29 Jun 2023 10:11:52 +0000 (12:11 +0200)
From `ip-link(8)`:
> [no]ignore-df - enables/disables IPv4 DF
                      suppression on this tunnel.  Normally datagrams
                      that exceed the MTU will be fragmented; the
                      presence of the DF flag inhibits this, resulting
                      instead in an ICMP Unreachable (Fragmentation
                      Required) message.  Enabling this attribute causes
                      the DF flag to be ignored.

If this option is enabled for a GRE/GRETAP tunnel, the `DF` flag in the outer IP header
will not inherit the inner IP header's `DF` flag.

This is useful to transfer packets that exceed the MTU of the underlay
network.

man/systemd.netdev.xml
src/network/netdev/netdev-gperf.gperf
src/network/netdev/tunnel.c
src/network/netdev/tunnel.h
test/test-network/conf/25-erspan0-tunnel.netdev
test/test-network/conf/25-gretap-tunnel.netdev
test/test-network/systemd-networkd-tests.py

index ed765e1b9c9faa187e299667dbde220219c4a628..5b5536df908037cee44ab99c0411918b16578e23 100644 (file)
         <term><varname>DiscoverPathMTU=</varname></term>
         <listitem>
           <para>Takes a boolean. When true, enables Path MTU Discovery on
-          the tunnel.</para>
+          the tunnel.
+          When <varname>IgnoreDontFragment=</varname> is enabled,
+          defaults to false. Otherwise, defaults to true.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>IgnoreDontFragment=</varname></term>
+        <listitem>
+          <para>Takes a boolean. When true, enables IPv4 Don't Fragment (DF) suppression on
+          the tunnel. Defaults to false.
+          Note that if <varname>IgnoreDontFragment=</varname> is set to true,
+          <varname>DiscoverPathMTU=</varname> cannot be set to true.
+          Only applicable to GRE, GRETAP, and ERSPAN tunnels.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
index ade5b1b91940b83d8536977d1d1336c829da316e..d5aa522de8d2b8864bbe5285f56d7ea3d560963e 100644 (file)
@@ -77,7 +77,8 @@ Tunnel.TTL,                               config_parse_unsigned,
 Tunnel.Key,                               config_parse_tunnel_key,                   0,                             offsetof(Tunnel, key)
 Tunnel.InputKey,                          config_parse_tunnel_key,                   0,                             offsetof(Tunnel, ikey)
 Tunnel.OutputKey,                         config_parse_tunnel_key,                   0,                             offsetof(Tunnel, okey)
-Tunnel.DiscoverPathMTU,                   config_parse_bool,                         0,                             offsetof(Tunnel, pmtudisc)
+Tunnel.DiscoverPathMTU,                   config_parse_tristate,                     0,                             offsetof(Tunnel, pmtudisc)
+Tunnel.IgnoreDontFragment,                config_parse_bool,                         0,                             offsetof(Tunnel, ignore_df)
 Tunnel.Mode,                              config_parse_ip6tnl_mode,                  0,                             offsetof(Tunnel, ip6tnl_mode)
 Tunnel.IPv6FlowLabel,                     config_parse_ipv6_flowlabel,               0,                             0
 Tunnel.CopyDSCP,                          config_parse_bool,                         0,                             offsetof(Tunnel, copy_dscp)
index 2addfeecaa818ba87d25073b04408be492cffeaa..881be3c405b9e45622c616076ecf8318f2fa2656 100644 (file)
@@ -378,6 +378,10 @@ static int netdev_gre_erspan_fill_message_create(NetDev *netdev, Link *link, sd_
         if (r < 0)
                 return r;
 
+        r = sd_netlink_message_append_u8(m, IFLA_GRE_IGNORE_DF, t->ignore_df);
+        if (r < 0)
+                return r;
+
         if (t->key != 0) {
                 ikey = okey = htobe32(t->key);
                 iflags |= GRE_KEY;
@@ -746,6 +750,11 @@ static int netdev_tunnel_verify(NetDev *netdev, const char *filename) {
                                               "The local address cannot be '%s' when Independent= or AssignToLoopback= is enabled, ignoring.",
                                               strna(netdev_local_address_type_to_string(t->local_type)));
 
+        if (t->pmtudisc > 0 && t->ignore_df)
+                return log_netdev_error_errno(netdev, SYNTHETIC_ERRNO(EINVAL),
+                                              "IgnoreDontFragment= cannot be enabled when DiscoverPathMTU= is enabled");
+        if (t->pmtudisc < 0)
+                t->pmtudisc = !t->ignore_df;
         return 0;
 }
 
@@ -1189,7 +1198,7 @@ static void netdev_tunnel_init(NetDev *netdev) {
         assert(t);
 
         t->local_type = _NETDEV_LOCAL_ADDRESS_TYPE_INVALID;
-        t->pmtudisc = true;
+        t->pmtudisc = -1;
         t->fou_encap_type = NETDEV_FOO_OVER_UDP_ENCAP_DIRECT;
         t->isatap = -1;
         t->gre_erspan_sequence = -1;
index 7c81f2239162c376c2e8abddded48bcf70894fe8..713f2fbf37695df6250437d29614c309a5873980 100644 (file)
@@ -54,7 +54,8 @@ typedef struct Tunnel {
         Ip6TnlMode ip6tnl_mode;
         FooOverUDPEncapType fou_encap_type;
 
-        bool pmtudisc;
+        int pmtudisc;
+        bool ignore_df;
         bool copy_dscp;
         bool independent;
         bool fou_tunnel;
index ee295d901f6f2487887021c51136ce9bcfc67c16..0ed03803a62271f2b1f100a7cea4b0e07053aa20 100644 (file)
@@ -13,3 +13,4 @@ Local = 172.16.1.200
 Remote = 172.16.1.100
 Key=101
 SerializeTunneledPackets=true
+IgnoreDontFragment=true
index 86ac3f7c5b196ca9f264937fb763c067e8ffb551..af5ea2fb2b04b89e753526aefdb5da2056e88fb7 100644 (file)
@@ -8,3 +8,4 @@ Local=10.65.223.238
 Remote=10.65.223.239
 Key=106
 SerializeTunneledPackets=true
+IgnoreDontFragment=true
index b5ef83a9c08b24253bb953f2f8070197162fe4a1..c068f37a8a0e2534f9db4c6300d5742a7bb7a297 100755 (executable)
@@ -1796,6 +1796,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertRegex(output, 'okey 0.0.0.106')
         self.assertRegex(output, 'iseq')
         self.assertRegex(output, 'oseq')
+        self.assertIn('nopmtudisc', output)
+        self.assertIn('ignore-df', output)
         output = check_output('ip -d link show gretap98')
         print(output)
         self.assertRegex(output, 'gretap remote 10.65.223.239 local any dev dummy98')
@@ -1955,6 +1957,8 @@ class NetworkdNetDevTests(unittest.TestCase, Utilities):
         self.assertNotIn('erspan_hwid 1f', output)
         self.assertIn('ikey 0.0.0.101', output)
         self.assertIn('iseq', output)
+        self.assertIn('nopmtudisc', output)
+        self.assertIn('ignore-df', output)
         output = check_output('ip -d link show erspan98')
         print(output)
         self.assertIn('erspan remote 172.16.1.100 local any', output)