diff mbox series

[RFC,net-next,07/11] net: gre: constrain upper VLAN MTU using IFF_NO_VLAN_ROOM

Message ID 20200527212512.17901-8-edwin.peer@broadcom.com
State New
Headers show
Series [RFC,net-next,01/11] net: geneve: enable vlan offloads | expand

Commit Message

Edwin Peer May 27, 2020, 9:25 p.m. UTC
Constrain the MTU of upper VLAN devices if the MTU of the GRE device
is configured to its default optimal size, which does not leave space
for a nested VLAN tag without causing fragmentation. If the underlying
lower device is not known, then the worst case is assumed and any upper
VLAN devices will always be adjusted to accommodate the VLAN tag.

For IPv4 tunnels, the changes to support this are made in the generic
ip_tunnel_change_mtu() handler and so IFF_NO_VLAN_ROOM is consequently
maintained for all tunnel devices that leverage this implementation. GRE
is, however, the only one of these implementations that might use an L2
overlay. At present nothing prevents VLAN devices being layered above
raw IP tunnel devices, which does not make sense. This limitation will
be addressed by a later patch in this series.

IPv6 GRE is dependent on PMTU discovery, but the MTU of nested VLANs
still need to be constrained, because non-VLAN packets will share the
same path MTU.

Signed-off-by: Edwin Peer <edwin.peer@broadcom.com>
---
 net/ipv4/ip_tunnel.c | 2 ++
 net/ipv6/ip6_gre.c   | 4 +++-
 2 files changed, 5 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index f4f1d11eab50..21803bd35ab3 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -981,6 +981,7 @@  int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
 	struct ip_tunnel *tunnel = netdev_priv(dev);
 	int t_hlen = tunnel->hlen + sizeof(struct iphdr);
 	int max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen;
+	int best_mtu = ip_tunnel_bind_dev(dev);
 
 	if (new_mtu < ETH_MIN_MTU)
 		return -EINVAL;
@@ -993,6 +994,7 @@  int __ip_tunnel_change_mtu(struct net_device *dev, int new_mtu, bool strict)
 	}
 
 	dev->mtu = new_mtu;
+	__vlan_constrain_mtu(dev, best_mtu);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(__ip_tunnel_change_mtu);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 781ca8c07a0d..0b86ee7f3d31 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1131,6 +1131,8 @@  static void ip6gre_tnl_link_config_route(struct ip6_tnl *t, int set_mtu,
 
 				if (dev->mtu < IPV6_MIN_MTU)
 					dev->mtu = IPV6_MIN_MTU;
+
+				dev->priv_flags |= IFF_NO_VLAN_ROOM;
 			}
 		}
 		ip6_rt_put(rt);
@@ -1801,7 +1803,7 @@  static int ip6gre_tap_init(struct net_device *dev)
 	if (ret)
 		return ret;
 
-	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
+	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE | IFF_NO_VLAN_ROOM;
 
 	return 0;
 }