forked from mirrors/linux
		
	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: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									67147ba99a
								
							
						
					
					
						commit
						78d3fd0b7d
					
				
					 2 changed files with 8 additions and 6 deletions
				
			
		| 
						 | 
					@ -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)
 | 
				
			||||||
	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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue