network: Add IgnoreDdontFragment= option for Fragmentation control (#28131)

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.
This commit is contained in:
Yuxiang Zhu 2023-06-29 18:11:52 +08:00 committed by GitHub
parent 9d5c20657a
commit b67e8a4e3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 33 additions and 4 deletions

View file

@ -1220,7 +1220,19 @@
<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>

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

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

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

View file

@ -13,3 +13,4 @@ Local = 172.16.1.200
Remote = 172.16.1.100
Key=101
SerializeTunneledPackets=true
IgnoreDontFragment=true

View file

@ -8,3 +8,4 @@ Local=10.65.223.238
Remote=10.65.223.239
Key=106
SerializeTunneledPackets=true
IgnoreDontFragment=true

View file

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