Message ID | 20100501.181558.141243424.davem@davemloft.net |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Le samedi 01 mai 2010 à 18:15 -0700, David Miller a écrit : > From: Eric Dumazet <eric.dumazet@gmail.com> > Date: Sat, 01 May 2010 08:42:25 +0200 > > > [PATCH net-next-2.6] net: eth_type_trans() should inline skb_pull() > > > > With RPS, this patch can give a 5 % boost in performance. > > > > Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> > > Awesome, but let's do this in a way that allows us to easily annotate > where inlining makes sense in other places, not just here. > > Something like this, ok? > > diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h > index 82f5116..746a652 100644 > --- a/include/linux/skbuff.h > +++ b/include/linux/skbuff.h > @@ -1128,6 +1128,11 @@ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) > return skb->data += len; > } > > +static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int len) > +{ > + return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); > +} > + > extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta); > > static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) > diff --git a/net/core/skbuff.c b/net/core/skbuff.c > index 4218ff4..8b9c109 100644 > --- a/net/core/skbuff.c > +++ b/net/core/skbuff.c > @@ -1051,7 +1051,7 @@ EXPORT_SYMBOL(skb_push); > */ > unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) > { > - return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); > + return skb_pull_inline(skb, len); > } > EXPORT_SYMBOL(skb_pull); > > diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c > index 0c0d272..61ec032 100644 > --- a/net/ethernet/eth.c > +++ b/net/ethernet/eth.c > @@ -162,7 +162,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) > > skb->dev = dev; > skb_reset_mac_header(skb); > - skb_pull(skb, ETH_HLEN); > + skb_pull_inline(skb, ETH_HLEN); > eth = eth_hdr(skb); > > if (unlikely(is_multicast_ether_addr(eth->h_dest))) { Excellent ! Changli privately asked me why we were ignoring cases where skb->len < ETH_HLEN. I replied that minimum frame size was 46+12, then he asked me why we were testing another time : if (skb->len >= 2 && *(unsigned short *)rawp == 0xFFFF) return htons(ETH_P_802_3); Could we assume all eth_type_trans() must call it with initial skb->len >= (46 + 12) or not ? (According to ethernet specs, all frames should have a minimum payload of 46 bytes) If not sure, maybe we should issue a WARN_ON_ONCE() If yes, tests could be removed and we could gain two cycles ;) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Eric Dumazet <eric.dumazet@gmail.com> Date: Sun, 02 May 2010 08:50:32 +0200 > Excellent ! Great, here is the commit message I will use: -------------------- net: Inline skb_pull() in eth_type_trans(). In commit 6be8ac2f ("[NET]: uninline skb_pull, de-bloats a lot") we uninlined skb_pull. But in some critical paths it makes sense to inline this thing and it helps performance significantly. Create an skb_pull_inline() so that we can do this in a way that serves also as annotation. Based upon a patch by Eric Dumazet. Signed-off-by: David S. Miller <davem@davemloft.net> -------------------- > Could we assume all eth_type_trans() must call it with initial > skb->len >= (46 + 12) or not ? (According to ethernet specs, all > frames should have a minimum payload of 46 bytes) > > If not sure, maybe we should issue a WARN_ON_ONCE() > > If yes, tests could be removed and we could gain two cycles ;) Isn't the minimum ETH_ZLEN? But yes, regardless of whether the minimum ethernet frame is 58 or 60 bytes, we should require it's at least that big, and use that test consistently throughout. Anything smaller is a runt packet and should be tossed or marked as an error in some other way by the hardware. They should never make it to eth_type_trans(). -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 82f5116..746a652 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1128,6 +1128,11 @@ static inline unsigned char *__skb_pull(struct sk_buff *skb, unsigned int len) return skb->data += len; } +static inline unsigned char *skb_pull_inline(struct sk_buff *skb, unsigned int len) +{ + return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); +} + extern unsigned char *__pskb_pull_tail(struct sk_buff *skb, int delta); static inline unsigned char *__pskb_pull(struct sk_buff *skb, unsigned int len) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 4218ff4..8b9c109 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1051,7 +1051,7 @@ EXPORT_SYMBOL(skb_push); */ unsigned char *skb_pull(struct sk_buff *skb, unsigned int len) { - return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); + return skb_pull_inline(skb, len); } EXPORT_SYMBOL(skb_pull); diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 0c0d272..61ec032 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c @@ -162,7 +162,7 @@ __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) skb->dev = dev; skb_reset_mac_header(skb); - skb_pull(skb, ETH_HLEN); + skb_pull_inline(skb, ETH_HLEN); eth = eth_hdr(skb); if (unlikely(is_multicast_ether_addr(eth->h_dest))) {