udp: Support UDP fraglist GRO/GSO.
This patch extends UDP GRO to support fraglist GRO/GSO by using the previously introduced infrastructure. If the feature is enabled, all UDP packets are going to fraglist GRO (local input and forward). After validating the csum, we mark ip_summed as CHECKSUM_UNNECESSARY for fraglist GRO packets to make sure that the csum is not touched. Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Reviewed-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
这个提交包含在:
@@ -115,8 +115,10 @@ INDIRECT_CALLABLE_SCOPE
|
||||
struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
{
|
||||
struct udphdr *uh = udp_gro_udphdr(skb);
|
||||
struct sk_buff *pp;
|
||||
struct sock *sk;
|
||||
|
||||
if (unlikely(!uh) || !static_branch_unlikely(&udpv6_encap_needed_key))
|
||||
if (unlikely(!uh))
|
||||
goto flush;
|
||||
|
||||
/* Don't bother verifying checksum if we're going to flush anyway. */
|
||||
@@ -132,7 +134,11 @@ struct sk_buff *udp6_gro_receive(struct list_head *head, struct sk_buff *skb)
|
||||
|
||||
skip:
|
||||
NAPI_GRO_CB(skb)->is_ipv6 = 1;
|
||||
return udp_gro_receive(head, skb, uh, udp6_lib_lookup_skb);
|
||||
rcu_read_lock();
|
||||
sk = static_branch_unlikely(&udpv6_encap_needed_key) ? udp6_lib_lookup_skb(skb, uh->source, uh->dest) : NULL;
|
||||
pp = udp_gro_receive(head, skb, uh, sk);
|
||||
rcu_read_unlock();
|
||||
return pp;
|
||||
|
||||
flush:
|
||||
NAPI_GRO_CB(skb)->flush = 1;
|
||||
@@ -144,6 +150,23 @@ INDIRECT_CALLABLE_SCOPE int udp6_gro_complete(struct sk_buff *skb, int nhoff)
|
||||
const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
struct udphdr *uh = (struct udphdr *)(skb->data + nhoff);
|
||||
|
||||
if (NAPI_GRO_CB(skb)->is_flist) {
|
||||
uh->len = htons(skb->len - nhoff);
|
||||
|
||||
skb_shinfo(skb)->gso_type |= (SKB_GSO_FRAGLIST|SKB_GSO_UDP_L4);
|
||||
skb_shinfo(skb)->gso_segs = NAPI_GRO_CB(skb)->count;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
|
||||
if (skb->csum_level < SKB_MAX_CSUM_LEVEL)
|
||||
skb->csum_level++;
|
||||
} else {
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb->csum_level = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uh->check)
|
||||
uh->check = ~udp_v6_check(skb->len - nhoff, &ipv6h->saddr,
|
||||
&ipv6h->daddr, 0);
|
||||
|
在新工单中引用
屏蔽一个用户