]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ip6_tunnel: Fix broken GRO
authorThomas Bogendoerfer <tbogendoerfer@suse.de>
Thu, 15 Aug 2024 15:14:16 +0000 (17:14 +0200)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 20 Aug 2024 11:21:10 +0000 (13:21 +0200)
GRO code checks for matching layer 2 headers to see, if packet belongs
to the same flow and because ip6 tunnel set dev->hard_header_len
this check fails in cases, where it shouldn't. To fix this don't
set hard_header_len, but use needed_headroom like ipv4/ip_tunnel.c
does.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Link: https://patch.msgid.link/20240815151419.109864-1-tbogendoerfer@suse.de
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/ipv6/ip6_tunnel.c

index 9dee0c12795540df27edfa7d19b797fe0ef0e855..87dfb565a9f81b663a06f07df63d2604c9a85cac 100644 (file)
@@ -1507,7 +1507,8 @@ static void ip6_tnl_link_config(struct ip6_tnl *t)
                        tdev = __dev_get_by_index(t->net, p->link);
 
                if (tdev) {
-                       dev->hard_header_len = tdev->hard_header_len + t_hlen;
+                       dev->needed_headroom = tdev->hard_header_len +
+                               tdev->needed_headroom + t_hlen;
                        mtu = min_t(unsigned int, tdev->mtu, IP6_MAX_MTU);
 
                        mtu = mtu - t_hlen;
@@ -1731,7 +1732,9 @@ ip6_tnl_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
 int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct ip6_tnl *tnl = netdev_priv(dev);
+       int t_hlen;
 
+       t_hlen = tnl->hlen + sizeof(struct ipv6hdr);
        if (tnl->parms.proto == IPPROTO_IPV6) {
                if (new_mtu < IPV6_MIN_MTU)
                        return -EINVAL;
@@ -1740,10 +1743,10 @@ int ip6_tnl_change_mtu(struct net_device *dev, int new_mtu)
                        return -EINVAL;
        }
        if (tnl->parms.proto == IPPROTO_IPV6 || tnl->parms.proto == 0) {
-               if (new_mtu > IP6_MAX_MTU - dev->hard_header_len)
+               if (new_mtu > IP6_MAX_MTU - dev->hard_header_len - t_hlen)
                        return -EINVAL;
        } else {
-               if (new_mtu > IP_MAX_MTU - dev->hard_header_len)
+               if (new_mtu > IP_MAX_MTU - dev->hard_header_len - t_hlen)
                        return -EINVAL;
        }
        WRITE_ONCE(dev->mtu, new_mtu);
@@ -1887,12 +1890,11 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        t_hlen = t->hlen + sizeof(struct ipv6hdr);
 
        dev->type = ARPHRD_TUNNEL6;
-       dev->hard_header_len = LL_MAX_HEADER + t_hlen;
        dev->mtu = ETH_DATA_LEN - t_hlen;
        if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
                dev->mtu -= 8;
        dev->min_mtu = ETH_MIN_MTU;
-       dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len;
+       dev->max_mtu = IP6_MAX_MTU - dev->hard_header_len - t_hlen;
 
        netdev_hold(dev, &t->dev_tracker, GFP_KERNEL);
        netdev_lockdep_set_classes(dev);