aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2014-10-03 23:59:19 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-06 00:37:30 -0400
commitbec3cfdca36bf43cfa3751ad7b56db1a307e0760 (patch)
treed9c2d8352b0cc41d43dc23b7a7eafdac6758aeb3 /net/core
parent45d9cc7c609680e921060d3eb4e399043eb5e4be (diff)
net: skb_segment() provides list head and tail
Its unfortunate we have to walk again skb list to find the tail after segmentation, even if data is probably hot in cpu caches. skb_segment() can store the tail of the list into segs->prev, and validate_xmit_skb_list() can immediately get the tail. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c27
-rw-r--r--net/core/skbuff.c5
2 files changed, 20 insertions, 12 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1a90530f83ff..7d5691cc1f47 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2724,22 +2724,25 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
2724{ 2724{
2725 struct sk_buff *next, *head = NULL, *tail; 2725 struct sk_buff *next, *head = NULL, *tail;
2726 2726
2727 while (skb) { 2727 for (; skb != NULL; skb = next) {
2728 next = skb->next; 2728 next = skb->next;
2729 skb->next = NULL; 2729 skb->next = NULL;
2730
2731 /* in case skb wont be segmented, point to itself */
2732 skb->prev = skb;
2733
2730 skb = validate_xmit_skb(skb, dev); 2734 skb = validate_xmit_skb(skb, dev);
2731 if (skb) { 2735 if (!skb)
2732 struct sk_buff *end = skb; 2736 continue;
2733 2737
2734 while (end->next) 2738 if (!head)
2735 end = end->next; 2739 head = skb;
2736 if (!head) 2740 else
2737 head = skb; 2741 tail->next = skb;
2738 else 2742 /* If skb was segmented, skb->prev points to
2739 tail->next = skb; 2743 * the last segment. If not, it still contains skb.
2740 tail = end; 2744 */
2741 } 2745 tail = skb->prev;
2742 skb = next;
2743 } 2746 }
2744 return head; 2747 return head;
2745} 2748}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 9a423e2c5766..7b3df0d518ab 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3083,6 +3083,11 @@ perform_csum_check:
3083 } 3083 }
3084 } while ((offset += len) < head_skb->len); 3084 } while ((offset += len) < head_skb->len);
3085 3085
3086 /* Some callers want to get the end of the list.
3087 * Put it in segs->prev to avoid walking the list.
3088 * (see validate_xmit_skb_list() for example)
3089 */
3090 segs->prev = tail;
3086 return segs; 3091 return segs;
3087 3092
3088err: 3093err: