From: Vadim Fedorenko vfedorenko@novek.ru
commit 28e104d00281ade30250b24e098bf50887671ea4 upstream.
dev->hard_header_len for tunnel interface is set only when header_ops are set too and already contains full overhead of any tunnel encapsulation. That's why there is not need to use this overhead twice in mtu calc.
Fixes: fdafed459998 ("ip_gre: set dev->hard_header_len and dev->needed_headroom properly") Reported-by: Slava Bacherikov mail@slava.cc Signed-off-by: Vadim Fedorenko vfedorenko@novek.ru Link: https://lore.kernel.org/r/1611959267-20536-1-git-send-email-vfedorenko@novek... Signed-off-by: Jakub Kicinski kuba@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- net/ipv4/ip_tunnel.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
--- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -330,7 +330,7 @@ static int ip_tunnel_bind_dev(struct net }
dev->needed_headroom = t_hlen + hlen; - mtu -= (dev->hard_header_len + t_hlen); + mtu -= t_hlen;
if (mtu < IPV4_MIN_MTU) mtu = IPV4_MIN_MTU; @@ -360,7 +360,7 @@ static struct ip_tunnel *ip_tunnel_creat nt = netdev_priv(dev); t_hlen = nt->hlen + sizeof(struct iphdr); dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = IP_MAX_MTU - dev->hard_header_len - t_hlen; + dev->max_mtu = IP_MAX_MTU - t_hlen; ip_tunnel_add(itn, nt); return nt;
@@ -502,12 +502,11 @@ static int tnl_update_pmtu(struct net_de const struct iphdr *inner_iph) { struct ip_tunnel *tunnel = netdev_priv(dev); - int pkt_size = skb->len - tunnel->hlen - dev->hard_header_len; + int pkt_size = skb->len - tunnel->hlen; int mtu;
if (df) - mtu = dst_mtu(&rt->dst) - dev->hard_header_len - - sizeof(struct iphdr) - tunnel->hlen; + mtu = dst_mtu(&rt->dst) - (sizeof(struct iphdr) + tunnel->hlen); else mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
@@ -935,7 +934,7 @@ int __ip_tunnel_change_mtu(struct net_de { 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 max_mtu = IP_MAX_MTU - t_hlen;
if (new_mtu < ETH_MIN_MTU) return -EINVAL; @@ -1112,10 +1111,9 @@ int ip_tunnel_newlink(struct net_device
mtu = ip_tunnel_bind_dev(dev); if (tb[IFLA_MTU]) { - unsigned int max = IP_MAX_MTU - dev->hard_header_len - nt->hlen; + unsigned int max = IP_MAX_MTU - (nt->hlen + sizeof(struct iphdr));
- mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, - (unsigned int)(max - sizeof(struct iphdr))); + mtu = clamp(dev->mtu, (unsigned int)ETH_MIN_MTU, max); }
err = dev_set_mtu(dev, mtu);