net: gro: skb_gro_header helper function
Subsystems (4)
PATCH v2 1/1 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 patternskb_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.
--- 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(-)
drivers/net/geneve.c +3 -6
@@ -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;
drivers/net/vxlan/vxlan_core.c +3 -6
@@ -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 ));
include/net/gro.h +18 -15
@@ -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; }
net/8021q/vlan_core.c +3 -6
@@ -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;
net/ethernet/eth.c +3 -6
@@ -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 ;
net/ipv4/af_inet.c +3 -6
@@ -1447,12 +1447,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;
net/ipv4/fou.c +3 -6
@@ -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 :
net/ipv4/gre_offload.c +3 -6
@@ -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
net/ipv4/tcp_offload.c +3 -6
@@ -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))
net/ipv6/ip6_offload.c +3 -6
@@ -197,12 +197,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));
Signature · 1 line
2.20.1
Jakub Kicinski
maintainerQuoted 4 lines · On Tue, 2 Aug 2022 16:38:02 +0200 Richard Gobert wrote:
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.
Quoted 8 lines
This leads to the pattern
skb_gro_header_fast->skb_gro_header_hard->skb_gro_header_slowrecurring many times throughout GRO code.This patch replaces these patterns with a single inlined function call, improving code readability.
Signed-off-by Richard Gobert <[email protected]>
# Form letter - net-next is closed
The merge window for Linux 6.0 has started and therefore net-next is closed for new drivers, features, code refactoring and optimizations. We are currently accepting bug fixes only.
Please repost when net-next reopens after 6.0-rc1 is cut.
RFC patches sent for review only are obviously welcome at any time.