Commit 78d3fd0b authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller

gro: Only use skb_gro_header for completely non-linear packets

Currently skb_gro_header is used for packets which put the hardware
header in skb->data with the rest in frags.  Since the drivers that
need this optimisation all provide completely non-linear packets,
we can gain extra optimisations by only performing the frag0
optimisation for completely non-linear packets.

In particular, we can simply test frag0 (instead of skb_headlen)
to see whether the optimisation is in force.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 67147ba9
...@@ -1135,22 +1135,23 @@ static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen) ...@@ -1135,22 +1135,23 @@ static inline void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
hlen += offset; hlen += offset;
if (!NAPI_GRO_CB(skb)->frag0 || if (!NAPI_GRO_CB(skb)->frag0 ||
unlikely(skb_shinfo(skb)->frags[0].size + skb_headlen(skb) < hlen)) unlikely(skb_shinfo(skb)->frags[0].size < hlen)) {
NAPI_GRO_CB(skb)->frag0 = NULL;
return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
}
return NAPI_GRO_CB(skb)->frag0 + offset; return NAPI_GRO_CB(skb)->frag0 + offset;
} }
static inline void *skb_gro_mac_header(struct sk_buff *skb) static inline void *skb_gro_mac_header(struct sk_buff *skb)
{ {
return skb_headlen(skb) ? skb_mac_header(skb) : return NAPI_GRO_CB(skb)->frag0 ?: skb_mac_header(skb);
NAPI_GRO_CB(skb)->frag0;
} }
static inline void *skb_gro_network_header(struct sk_buff *skb) static inline void *skb_gro_network_header(struct sk_buff *skb)
{ {
return skb_headlen(skb) ? skb_network_header(skb) : return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
NAPI_GRO_CB(skb)->frag0 + skb_network_offset(skb); skb_network_offset(skb);
} }
static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev, static inline int dev_hard_header(struct sk_buff *skb, struct net_device *dev,
......
...@@ -2510,7 +2510,8 @@ void skb_gro_reset_offset(struct sk_buff *skb) ...@@ -2510,7 +2510,8 @@ void skb_gro_reset_offset(struct sk_buff *skb)
NAPI_GRO_CB(skb)->data_offset = 0; NAPI_GRO_CB(skb)->data_offset = 0;
NAPI_GRO_CB(skb)->frag0 = NULL; NAPI_GRO_CB(skb)->frag0 = NULL;
if (!skb_headlen(skb) && !PageHighMem(skb_shinfo(skb)->frags[0].page)) if (skb->mac_header == skb->tail &&
!PageHighMem(skb_shinfo(skb)->frags[0].page))
NAPI_GRO_CB(skb)->frag0 = NAPI_GRO_CB(skb)->frag0 =
page_address(skb_shinfo(skb)->frags[0].page) + page_address(skb_shinfo(skb)->frags[0].page) +
skb_shinfo(skb)->frags[0].page_offset; skb_shinfo(skb)->frags[0].page_offset;
......
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