diff --git a/man/systemd.netdev.xml b/man/systemd.netdev.xml
index ed765e1b9c..5b5536df90 100644
--- a/man/systemd.netdev.xml
+++ b/man/systemd.netdev.xml
@@ -1220,7 +1220,19 @@
DiscoverPathMTU=
Takes a boolean. When true, enables Path MTU Discovery on
- the tunnel.
+ the tunnel.
+ When IgnoreDontFragment= is enabled,
+ defaults to false. Otherwise, defaults to true.
+
+
+
+ IgnoreDontFragment=
+
+ Takes a boolean. When true, enables IPv4 Don't Fragment (DF) suppression on
+ the tunnel. Defaults to false.
+ Note that if IgnoreDontFragment= is set to true,
+ DiscoverPathMTU= cannot be set to true.
+ Only applicable to GRE, GRETAP, and ERSPAN tunnels.
diff --git a/src/network/netdev/netdev-gperf.gperf b/src/network/netdev/netdev-gperf.gperf
index ade5b1b919..d5aa522de8 100644
--- a/src/network/netdev/netdev-gperf.gperf
+++ b/src/network/netdev/netdev-gperf.gperf
@@ -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)
diff --git a/src/network/netdev/tunnel.c b/src/network/netdev/tunnel.c
index 2addfeecaa..881be3c405 100644
--- a/src/network/netdev/tunnel.c
+++ b/src/network/netdev/tunnel.c
@@ -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;
diff --git a/src/network/netdev/tunnel.h b/src/network/netdev/tunnel.h
index 7c81f22391..713f2fbf37 100644
--- a/src/network/netdev/tunnel.h
+++ b/src/network/netdev/tunnel.h
@@ -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;
diff --git a/test/test-network/conf/25-erspan0-tunnel.netdev b/test/test-network/conf/25-erspan0-tunnel.netdev
index ee295d901f..0ed03803a6 100644
--- a/test/test-network/conf/25-erspan0-tunnel.netdev
+++ b/test/test-network/conf/25-erspan0-tunnel.netdev
@@ -13,3 +13,4 @@ Local = 172.16.1.200
Remote = 172.16.1.100
Key=101
SerializeTunneledPackets=true
+IgnoreDontFragment=true
diff --git a/test/test-network/conf/25-gretap-tunnel.netdev b/test/test-network/conf/25-gretap-tunnel.netdev
index 86ac3f7c5b..af5ea2fb2b 100644
--- a/test/test-network/conf/25-gretap-tunnel.netdev
+++ b/test/test-network/conf/25-gretap-tunnel.netdev
@@ -8,3 +8,4 @@ Local=10.65.223.238
Remote=10.65.223.239
Key=106
SerializeTunneledPackets=true
+IgnoreDontFragment=true
diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py
index b5ef83a9c0..c068f37a8a 100755
--- a/test/test-network/systemd-networkd-tests.py
+++ b/test/test-network/systemd-networkd-tests.py
@@ -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)