ipv6: refactor ip6_finish_output for GSO handling
Separate GSO and non-GSO packets handling to make the logic cleaner. For GSO packets, frag_max_size check can be omitted because it is only useful for packets defragmented by netfilter hooks. Both local output and GRO logic won't produce GSO packets when defragment is needed. This also mirrors what IPv4 side code is doing. Suggested-by: Florian Westphal <fw@strlen.de> Signed-off-by: Yan Zhai <yan@cloudflare.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Reviewed-by: Eric Dumazet <edumazet@google.com> Link: https://lore.kernel.org/r/0e1d4599f858e2becff5c4fe0b5f843236bc3fe8.1698156966.git.yan@cloudflare.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
e57a344785
commit
1f7ec1b372
@ -172,6 +172,16 @@ ip6_finish_output_gso_slowpath_drop(struct net *net, struct sock *sk,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ip6_finish_output_gso(struct net *net, struct sock *sk,
|
||||
struct sk_buff *skb, unsigned int mtu)
|
||||
{
|
||||
if (!(IP6CB(skb)->flags & IP6SKB_FAKEJUMBO) &&
|
||||
!skb_gso_validate_network_len(skb, mtu))
|
||||
return ip6_finish_output_gso_slowpath_drop(net, sk, skb, mtu);
|
||||
|
||||
return ip6_finish_output2(net, sk, skb);
|
||||
}
|
||||
|
||||
static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
unsigned int mtu;
|
||||
@ -185,16 +195,14 @@ static int __ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff
|
||||
#endif
|
||||
|
||||
mtu = ip6_skb_dst_mtu(skb);
|
||||
if (skb_is_gso(skb) &&
|
||||
!(IP6CB(skb)->flags & IP6SKB_FAKEJUMBO) &&
|
||||
!skb_gso_validate_network_len(skb, mtu))
|
||||
return ip6_finish_output_gso_slowpath_drop(net, sk, skb, mtu);
|
||||
if (skb_is_gso(skb))
|
||||
return ip6_finish_output_gso(net, sk, skb, mtu);
|
||||
|
||||
if ((skb->len > mtu && !skb_is_gso(skb)) ||
|
||||
if (skb->len > mtu ||
|
||||
(IP6CB(skb)->frag_max_size && skb->len > IP6CB(skb)->frag_max_size))
|
||||
return ip6_fragment(net, sk, skb, ip6_finish_output2);
|
||||
else
|
||||
return ip6_finish_output2(net, sk, skb);
|
||||
|
||||
return ip6_finish_output2(net, sk, skb);
|
||||
}
|
||||
|
||||
static int ip6_finish_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
|
Loading…
Reference in New Issue
Block a user