From 35ffb66547295c72650978f9c28e670e014d0957 Mon Sep 17 00:00:00 2001 From: Richard Gobert Date: Tue, 23 Aug 2022 09:10:49 +0200 Subject: [PATCH] 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: Richard Gobert Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/20220823071034.GA56142@debian Signed-off-by: Paolo Abeni --- drivers/net/geneve.c | 9 +++------ drivers/net/vxlan/vxlan_core.c | 9 +++------ include/net/gro.h | 33 ++++++++++++++++++--------------- net/8021q/vlan_core.c | 9 +++------ net/ethernet/eth.c | 9 +++------ net/ipv4/af_inet.c | 9 +++------ net/ipv4/fou.c | 9 +++------ net/ipv4/gre_offload.c | 9 +++------ net/ipv4/tcp_offload.c | 9 +++------ net/ipv6/ip6_offload.c | 9 +++------ 10 files changed, 45 insertions(+), 69 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 7962c37b3f14..01aa94776ce3 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -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; diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index c3285242f74f..1a47d04f5d1a 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -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)); diff --git a/include/net/gro.h b/include/net/gro.h index 867656b0739c..5bf15c212434 100644 --- a/include/net/gro.h +++ b/include/net/gro.h @@ -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) + @@ -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); @@ -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); } @@ -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; } diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 5aa8144101dc..0beb44f2fe1f 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -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; diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 62b89d6f54fd..e02daa74e833 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -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; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 2e6a3cb06815..d3ab1ae32ef5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -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; diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c index 025a33c1b04d..cb5bfb77944c 100644 --- a/net/ipv4/fou.c +++ b/net/ipv4/fou.c @@ -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: diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 07073fa35205..2b9cb5398335 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -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 diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 30abde86db45..a844a0d38482 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c @@ -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)) diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index d12dba2dd535..d37a8c97e6de 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c @@ -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));