Signed-off-by: Solomon Peachy <[email protected]> This patch tweaks the skb_copy_bits() call in skb_copy() and skb_copy_expand(). In the sace of skb_copy(): if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)) Basically, this call assumes that n->head+headerlen == n->data. This is, fortunately, generally true. But if the alloc_skb function allocates extra head room (ie calls skb_reserve() on the skb before it passes it to the callee, this doesn't quite work. Instead, it should be rewritten as: if (skb_copy_bits(skb, -headerlen, n->data-headerlen, headerlen + skb->len)) Rewriting it this way works; n->data-headerlen is equal to n->data before the skb_reserve() call. This seems MoreCorrect(tm), as it makes no assumptions about the state of the skb passed into it. (n->data just so happens to equal n->head too) skb_copy_expand() has the same problem as well, and has a similar fix. This patch is against 2.6.12-rc4, though it should apply cleanly to any 2.4/2.6 kernel. ... The history behind this is a little sordid -- We were trying to implement a "poor man's zerocopy" transmit path for a braindead USB wireless controller. It needed a descriptor packet prepended to the frame contents, but couldn't handle it in a separate USB packet -- so we'd have to do a realloc on the skb to give us the headroom we eneded. memcpy()s on the very underpowered target were expensive, so we tried modifying skb_alloc to always ensure there would be enough headroom for the descriptor (allocating extra, and then skb_reserve()ing it). It was a crude hack, but it gained us a few much-needed percentage points of throughput. That is once we fixed skb_copy().. Anyway, please consider this patch for inclusion. - Solomon -- Solomon Peachy ICQ: 1318344 Melbourne, FL JID: [email protected] Quidquid latine dictum sit, altum viditur
--- /linux/net/core/skbuff.c 2005-05-08 09:57:37.000000000 -0400 +++ skbuff.c 2005-05-08 10:27:17.000000000 -0400 @@ -486,7 +486,7 @@ n->csum = skb->csum; n->ip_summed = skb->ip_summed; - if (skb_copy_bits(skb, -headerlen, n->head, headerlen + skb->len)) + if (skb_copy_bits(skb, -headerlen, n->data-headerlen, headerlen + skb->len)) BUG(); copy_skb_header(n, skb); @@ -680,7 +680,7 @@ head_copy_off = newheadroom - head_copy_len; /* Copy the linear header and data. */ - if (skb_copy_bits(skb, -head_copy_len, n->head + head_copy_off, + if (skb_copy_bits(skb, -head_copy_len, n->data-newheadroom + head_copy_off, skb->len + head_copy_len)) BUG();
Attachment:
pgpkJ0mOSK3jx.pgp
Description: PGP signature
- Follow-Ups:
- Re: [PATCH] fix long-standing bug in 2.6/2.4 skb_copy/skb_copy_expand
- From: "David S. Miller" <[email protected]>
- Re: [PATCH] fix long-standing bug in 2.6/2.4 skb_copy/skb_copy_expand
- From: Herbert Xu <[email protected]>
- Re: [PATCH] fix long-standing bug in 2.6/2.4 skb_copy/skb_copy_expand
- Prev by Date: Re: oprofile: enabling cpu events
- Next by Date: pthread question
- Previous by thread: Usb-Storage OOPS
- Next by thread: Re: [PATCH] fix long-standing bug in 2.6/2.4 skb_copy/skb_copy_expand
- Index(es):