Skip to content

Commit

Permalink
net: gro: skb_gro_header helper function
Browse files Browse the repository at this point in the history
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: Richard Gobert <richardbgobert@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://lore.kernel.org/r/20220823071034.GA56142@debian
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Richard Gobert authored and Paolo Abeni committed Aug 25, 2022
1 parent 77a70f9 commit 35ffb66
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 69 deletions.
9 changes: 3 additions & 6 deletions drivers/net/geneve.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,12 +503,9 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk,

off_gnv = skb_gro_offset(skb);
hlen = off_gnv + sizeof(*gh);
gh = skb_gro_header_fast(skb, off_gnv);
if (skb_gro_header_hard(skb, hlen)) {
gh = skb_gro_header_slow(skb, hlen, off_gnv);
if (unlikely(!gh))
goto out;
}
gh = skb_gro_header(skb, hlen, off_gnv);
if (unlikely(!gh))
goto out;

if (gh->ver != GENEVE_VER || gh->oam)
goto out;
Expand Down
9 changes: 3 additions & 6 deletions drivers/net/vxlan/vxlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,12 +713,9 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,

off_vx = skb_gro_offset(skb);
hlen = off_vx + sizeof(*vh);
vh = skb_gro_header_fast(skb, off_vx);
if (skb_gro_header_hard(skb, hlen)) {
vh = skb_gro_header_slow(skb, hlen, off_vx);
if (unlikely(!vh))
goto out;
}
vh = skb_gro_header(skb, hlen, off_vx);
if (unlikely(!vh))
goto out;

skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));

Expand Down
33 changes: 18 additions & 15 deletions include/net/gro.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,17 @@ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
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)
{
return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
Expand Down Expand Up @@ -301,12 +312,9 @@ static inline void *skb_gro_remcsum_process(struct sk_buff *skb, void *ptr,
return ptr;
}

ptr = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, off + plen)) {
ptr = skb_gro_header_slow(skb, off + plen, off);
if (!ptr)
return NULL;
}
ptr = skb_gro_header(skb, off + plen, off);
if (!ptr)
return NULL;

delta = remcsum_adjust(ptr + hdrlen, NAPI_GRO_CB(skb)->csum,
start, offset);
Expand All @@ -329,12 +337,9 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
if (!grc->delta)
return;

ptr = skb_gro_header_fast(skb, grc->offset);
if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) {
ptr = skb_gro_header_slow(skb, plen, grc->offset);
if (!ptr)
return;
}
ptr = skb_gro_header(skb, plen, grc->offset);
if (!ptr)
return;

remcsum_unadjust((__sum16 *)ptr, grc->delta);
}
Expand Down Expand Up @@ -405,9 +410,7 @@ static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)

off = skb_gro_offset(skb);
hlen = off + sizeof(*uh);
uh = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, hlen))
uh = skb_gro_header_slow(skb, hlen, off);
uh = skb_gro_header(skb, hlen, off);

return uh;
}
Expand Down
9 changes: 3 additions & 6 deletions net/8021q/vlan_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -467,12 +467,9 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,

off_vlan = skb_gro_offset(skb);
hlen = off_vlan + sizeof(*vhdr);
vhdr = skb_gro_header_fast(skb, off_vlan);
if (skb_gro_header_hard(skb, hlen)) {
vhdr = skb_gro_header_slow(skb, hlen, off_vlan);
if (unlikely(!vhdr))
goto out;
}
vhdr = skb_gro_header(skb, hlen, off_vlan);
if (unlikely(!vhdr))
goto out;

type = vhdr->h_vlan_encapsulated_proto;

Expand Down
9 changes: 3 additions & 6 deletions net/ethernet/eth.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,12 +414,9 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)

off_eth = skb_gro_offset(skb);
hlen = off_eth + sizeof(*eh);
eh = skb_gro_header_fast(skb, off_eth);
if (skb_gro_header_hard(skb, hlen)) {
eh = skb_gro_header_slow(skb, hlen, off_eth);
if (unlikely(!eh))
goto out;
}
eh = skb_gro_header(skb, hlen, off_eth);
if (unlikely(!eh))
goto out;

flush = 0;

Expand Down
9 changes: 3 additions & 6 deletions net/ipv4/af_inet.c
Original file line number Diff line number Diff line change
Expand Up @@ -1464,12 +1464,9 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)

off = skb_gro_offset(skb);
hlen = off + sizeof(*iph);
iph = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, hlen)) {
iph = skb_gro_header_slow(skb, hlen, off);
if (unlikely(!iph))
goto out;
}
iph = skb_gro_header(skb, hlen, off);
if (unlikely(!iph))
goto out;

proto = iph->protocol;

Expand Down
9 changes: 3 additions & 6 deletions net/ipv4/fou.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,12 +323,9 @@ static struct sk_buff *gue_gro_receive(struct sock *sk,
off = skb_gro_offset(skb);
len = off + sizeof(*guehdr);

guehdr = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, len)) {
guehdr = skb_gro_header_slow(skb, len, off);
if (unlikely(!guehdr))
goto out;
}
guehdr = skb_gro_header(skb, len, off);
if (unlikely(!guehdr))
goto out;

switch (guehdr->version) {
case 0:
Expand Down
9 changes: 3 additions & 6 deletions net/ipv4/gre_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,9 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,

off = skb_gro_offset(skb);
hlen = off + sizeof(*greh);
greh = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, hlen)) {
greh = skb_gro_header_slow(skb, hlen, off);
if (unlikely(!greh))
goto out;
}
greh = skb_gro_header(skb, hlen, off);
if (unlikely(!greh))
goto out;

/* Only support version 0 and K (key), C (csum) flags. Note that
* although the support for the S (seq#) flag can be added easily
Expand Down
9 changes: 3 additions & 6 deletions net/ipv4/tcp_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,9 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb)

off = skb_gro_offset(skb);
hlen = off + sizeof(*th);
th = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, hlen)) {
th = skb_gro_header_slow(skb, hlen, off);
if (unlikely(!th))
goto out;
}
th = skb_gro_header(skb, hlen, off);
if (unlikely(!th))
goto out;

thlen = th->doff * 4;
if (thlen < sizeof(*th))
Expand Down
9 changes: 3 additions & 6 deletions net/ipv6/ip6_offload.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,9 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,

off = skb_gro_offset(skb);
hlen = off + sizeof(*iph);
iph = skb_gro_header_fast(skb, off);
if (skb_gro_header_hard(skb, hlen)) {
iph = skb_gro_header_slow(skb, hlen, off);
if (unlikely(!iph))
goto out;
}
iph = skb_gro_header_slow(skb, hlen, off);
if (unlikely(!iph))
goto out;

skb_set_network_header(skb, off);
skb_gro_pull(skb, sizeof(*iph));
Expand Down

0 comments on commit 35ffb66

Please sign in to comment.