Skip to content

Commit

Permalink
net: skb_segment() provides list head and tail
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Oct 6, 2014
1 parent 45d9cc7 commit bec3cfd
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
27 changes: 15 additions & 12 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -2724,22 +2724,25 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d
{
struct sk_buff *next, *head = NULL, *tail;

while (skb) {
for (; skb != NULL; skb = next) {
next = skb->next;
skb->next = NULL;

/* in case skb wont be segmented, point to itself */
skb->prev = skb;

skb = validate_xmit_skb(skb, dev);
if (skb) {
struct sk_buff *end = skb;
if (!skb)
continue;

while (end->next)
end = end->next;
if (!head)
head = skb;
else
tail->next = skb;
tail = end;
}
skb = next;
if (!head)
head = skb;
else
tail->next = skb;
/* If skb was segmented, skb->prev points to
* the last segment. If not, it still contains skb.
*/
tail = skb->prev;
}
return head;
}
Expand Down
5 changes: 5 additions & 0 deletions net/core/skbuff.c
Original file line number Diff line number Diff line change
Expand Up @@ -3083,6 +3083,11 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
}
} while ((offset += len) < head_skb->len);

/* Some callers want to get the end of the list.
* Put it in segs->prev to avoid walking the list.
* (see validate_xmit_skb_list() for example)
*/
segs->prev = tail;
return segs;

err:
Expand Down

0 comments on commit bec3cfd

Please sign in to comment.