Commit 35ffb665 authored by Richard Gobert's avatar Richard Gobert Committed by Paolo Abeni

net: gro: skb_gro_header helper function

Introduce a simple helper function to replace a common pattern.
When accessing the GRO header, we fetch the pointer from frag0,
then test its validity and fetch it from the skb when necessary.

This leads to the pattern
skb_gro_header_fast -> skb_gro_header_hard -> skb_gro_header_slow
recurring many times throughout GRO code.

This patch replaces these patterns with a single inlined function
call, improving code readability.
Signed-off-by: default avatarRichard Gobert <richardbgobert@gmail.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20220823071034.GA56142@debianSigned-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 77a70f9c
...@@ -503,12 +503,9 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk, ...@@ -503,12 +503,9 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk,
off_gnv = skb_gro_offset(skb); off_gnv = skb_gro_offset(skb);
hlen = off_gnv + sizeof(*gh); hlen = off_gnv + sizeof(*gh);
gh = skb_gro_header_fast(skb, off_gnv); gh = skb_gro_header(skb, hlen, off_gnv);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!gh))
gh = skb_gro_header_slow(skb, hlen, off_gnv); goto out;
if (unlikely(!gh))
goto out;
}
if (gh->ver != GENEVE_VER || gh->oam) if (gh->ver != GENEVE_VER || gh->oam)
goto out; goto out;
......
...@@ -713,12 +713,9 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk, ...@@ -713,12 +713,9 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
off_vx = skb_gro_offset(skb); off_vx = skb_gro_offset(skb);
hlen = off_vx + sizeof(*vh); hlen = off_vx + sizeof(*vh);
vh = skb_gro_header_fast(skb, off_vx); vh = skb_gro_header(skb, hlen, off_vx);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!vh))
vh = skb_gro_header_slow(skb, hlen, off_vx); goto out;
if (unlikely(!vh))
goto out;
}
skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr)); skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
......
...@@ -160,6 +160,17 @@ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen, ...@@ -160,6 +160,17 @@ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
return skb->data + offset; return skb->data + offset;
} }
static inline void *skb_gro_header(struct sk_buff *skb,
unsigned int hlen, unsigned int offset)
{
void *ptr;
ptr = skb_gro_header_fast(skb, offset);
if (skb_gro_header_hard(skb, hlen))
ptr = skb_gro_header_slow(skb, hlen, offset);
return ptr;
}
static inline void *skb_gro_network_header(struct sk_buff *skb) static inline void *skb_gro_network_header(struct sk_buff *skb)
{ {
return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) + return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
...@@ -301,12 +312,9 @@ static inline void *skb_gro_remcsum_process(struct sk_buff *skb, void *ptr, ...@@ -301,12 +312,9 @@ static inline void *skb_gro_remcsum_process(struct sk_buff *skb, void *ptr,
return ptr; return ptr;
} }
ptr = skb_gro_header_fast(skb, off); ptr = skb_gro_header(skb, off + plen, off);
if (skb_gro_header_hard(skb, off + plen)) { if (!ptr)
ptr = skb_gro_header_slow(skb, off + plen, off); return NULL;
if (!ptr)
return NULL;
}
delta = remcsum_adjust(ptr + hdrlen, NAPI_GRO_CB(skb)->csum, delta = remcsum_adjust(ptr + hdrlen, NAPI_GRO_CB(skb)->csum,
start, offset); start, offset);
...@@ -329,12 +337,9 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb, ...@@ -329,12 +337,9 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
if (!grc->delta) if (!grc->delta)
return; return;
ptr = skb_gro_header_fast(skb, grc->offset); ptr = skb_gro_header(skb, plen, grc->offset);
if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) { if (!ptr)
ptr = skb_gro_header_slow(skb, plen, grc->offset); return;
if (!ptr)
return;
}
remcsum_unadjust((__sum16 *)ptr, grc->delta); remcsum_unadjust((__sum16 *)ptr, grc->delta);
} }
...@@ -405,9 +410,7 @@ static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb) ...@@ -405,9 +410,7 @@ static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
hlen = off + sizeof(*uh); hlen = off + sizeof(*uh);
uh = skb_gro_header_fast(skb, off); uh = skb_gro_header(skb, hlen, off);
if (skb_gro_header_hard(skb, hlen))
uh = skb_gro_header_slow(skb, hlen, off);
return uh; return uh;
} }
......
...@@ -467,12 +467,9 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head, ...@@ -467,12 +467,9 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
off_vlan = skb_gro_offset(skb); off_vlan = skb_gro_offset(skb);
hlen = off_vlan + sizeof(*vhdr); hlen = off_vlan + sizeof(*vhdr);
vhdr = skb_gro_header_fast(skb, off_vlan); vhdr = skb_gro_header(skb, hlen, off_vlan);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!vhdr))
vhdr = skb_gro_header_slow(skb, hlen, off_vlan); goto out;
if (unlikely(!vhdr))
goto out;
}
type = vhdr->h_vlan_encapsulated_proto; type = vhdr->h_vlan_encapsulated_proto;
......
...@@ -414,12 +414,9 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb) ...@@ -414,12 +414,9 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
off_eth = skb_gro_offset(skb); off_eth = skb_gro_offset(skb);
hlen = off_eth + sizeof(*eh); hlen = off_eth + sizeof(*eh);
eh = skb_gro_header_fast(skb, off_eth); eh = skb_gro_header(skb, hlen, off_eth);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!eh))
eh = skb_gro_header_slow(skb, hlen, off_eth); goto out;
if (unlikely(!eh))
goto out;
}
flush = 0; flush = 0;
......
...@@ -1464,12 +1464,9 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb) ...@@ -1464,12 +1464,9 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
hlen = off + sizeof(*iph); hlen = off + sizeof(*iph);
iph = skb_gro_header_fast(skb, off); iph = skb_gro_header(skb, hlen, off);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!iph))
iph = skb_gro_header_slow(skb, hlen, off); goto out;
if (unlikely(!iph))
goto out;
}
proto = iph->protocol; proto = iph->protocol;
......
...@@ -323,12 +323,9 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, ...@@ -323,12 +323,9 @@ static struct sk_buff *gue_gro_receive(struct sock *sk,
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
len = off + sizeof(*guehdr); len = off + sizeof(*guehdr);
guehdr = skb_gro_header_fast(skb, off); guehdr = skb_gro_header(skb, len, off);
if (skb_gro_header_hard(skb, len)) { if (unlikely(!guehdr))
guehdr = skb_gro_header_slow(skb, len, off); goto out;
if (unlikely(!guehdr))
goto out;
}
switch (guehdr->version) { switch (guehdr->version) {
case 0: case 0:
......
...@@ -137,12 +137,9 @@ static struct sk_buff *gre_gro_receive(struct list_head *head, ...@@ -137,12 +137,9 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
hlen = off + sizeof(*greh); hlen = off + sizeof(*greh);
greh = skb_gro_header_fast(skb, off); greh = skb_gro_header(skb, hlen, off);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!greh))
greh = skb_gro_header_slow(skb, hlen, off); goto out;
if (unlikely(!greh))
goto out;
}
/* Only support version 0 and K (key), C (csum) flags. Note that /* Only support version 0 and K (key), C (csum) flags. Note that
* although the support for the S (seq#) flag can be added easily * although the support for the S (seq#) flag can be added easily
......
...@@ -195,12 +195,9 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb) ...@@ -195,12 +195,9 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb)
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
hlen = off + sizeof(*th); hlen = off + sizeof(*th);
th = skb_gro_header_fast(skb, off); th = skb_gro_header(skb, hlen, off);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!th))
th = skb_gro_header_slow(skb, hlen, off); goto out;
if (unlikely(!th))
goto out;
}
thlen = th->doff * 4; thlen = th->doff * 4;
if (thlen < sizeof(*th)) if (thlen < sizeof(*th))
......
...@@ -219,12 +219,9 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head, ...@@ -219,12 +219,9 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
off = skb_gro_offset(skb); off = skb_gro_offset(skb);
hlen = off + sizeof(*iph); hlen = off + sizeof(*iph);
iph = skb_gro_header_fast(skb, off); iph = skb_gro_header_slow(skb, hlen, off);
if (skb_gro_header_hard(skb, hlen)) { if (unlikely(!iph))
iph = skb_gro_header_slow(skb, hlen, off); goto out;
if (unlikely(!iph))
goto out;
}
skb_set_network_header(skb, off); skb_set_network_header(skb, off);
skb_gro_pull(skb, sizeof(*iph)); skb_gro_pull(skb, sizeof(*iph));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment