Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: allow gro_max_size to exceed 65536

Allow the gro_max_size to exceed a value larger than 65536.

There weren't really any external limitations that prevented this other
than the fact that IPv4 only supports a 16 bit length field. Since we have
the option of adding a hop-by-hop header for IPv6 we can allow IPv6 to
exceed this value and for IPv4 and non-TCP flows we can cap things at 65536
via a constant rather than relying on gro_max_size.

[edumazet] limit GRO_MAX_SIZE to (8 * 65535) to avoid overflows.

Signed-off-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Alexander Duyck and committed by
David S. Miller
0fe79f28 81fbc812

+16 -12
+1 -1
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
··· 2038 2038 { 2039 2039 int nr_frags = skb_shinfo(skb)->nr_frags; 2040 2040 2041 - return PAGE_SIZE * nr_frags + data_bcnt <= GRO_MAX_SIZE; 2041 + return PAGE_SIZE * nr_frags + data_bcnt <= GRO_LEGACY_MAX_SIZE; 2042 2042 } 2043 2043 2044 2044 static void
+5 -1
include/linux/netdevice.h
··· 2161 2161 struct bpf_prog __rcu *xdp_prog; 2162 2162 unsigned long gro_flush_timeout; 2163 2163 int napi_defer_hard_irqs; 2164 - #define GRO_MAX_SIZE 65536 2164 + #define GRO_LEGACY_MAX_SIZE 65536u 2165 + /* TCP minimal MSS is 8 (TCP_MIN_GSO_SIZE), 2166 + * and shinfo->gso_segs is a 16bit field. 2167 + */ 2168 + #define GRO_MAX_SIZE (8 * 65535u) 2165 2169 unsigned int gro_max_size; 2166 2170 rx_handler_func_t __rcu *rx_handler; 2167 2171 void __rcu *rx_handler_data;
+1 -1
include/net/ipv6.h
··· 477 477 const struct hop_jumbo_hdr *jhdr; 478 478 const struct ipv6hdr *nhdr; 479 479 480 - if (likely(skb->len <= GRO_MAX_SIZE)) 480 + if (likely(skb->len <= GRO_LEGACY_MAX_SIZE)) 481 481 return 0; 482 482 483 483 if (skb->protocol != htons(ETH_P_IPV6))
+1 -1
net/core/dev.c
··· 10598 10598 10599 10599 dev->gso_max_size = GSO_LEGACY_MAX_SIZE; 10600 10600 dev->gso_max_segs = GSO_MAX_SEGS; 10601 - dev->gro_max_size = GRO_MAX_SIZE; 10601 + dev->gro_max_size = GRO_LEGACY_MAX_SIZE; 10602 10602 dev->tso_max_size = TSO_LEGACY_MAX_SIZE; 10603 10603 dev->tso_max_segs = TSO_MAX_SEGS; 10604 10604 dev->upper_level = 1;
+8
net/core/gro.c
··· 167 167 if (unlikely(p->len + len >= gro_max_size || NAPI_GRO_CB(skb)->flush)) 168 168 return -E2BIG; 169 169 170 + if (unlikely(p->len + len >= GRO_LEGACY_MAX_SIZE)) { 171 + if (p->protocol != htons(ETH_P_IPV6) || 172 + skb_headroom(p) < sizeof(struct hop_jumbo_hdr) || 173 + ipv6_hdr(p)->nexthdr != IPPROTO_TCP || 174 + p->encapsulation) 175 + return -E2BIG; 176 + } 177 + 170 178 lp = NAPI_GRO_CB(p)->last; 171 179 pinfo = skb_shinfo(lp); 172 180
-8
net/core/rtnetlink.c
··· 2360 2360 } 2361 2361 } 2362 2362 2363 - if (tb[IFLA_GRO_MAX_SIZE]) { 2364 - u32 gro_max_size = nla_get_u32(tb[IFLA_GRO_MAX_SIZE]); 2365 - 2366 - if (gro_max_size > GRO_MAX_SIZE) { 2367 - NL_SET_ERR_MSG(extack, "too big gro_max_size"); 2368 - return -EINVAL; 2369 - } 2370 - } 2371 2363 return 0; 2372 2364 } 2373 2365