RE: skbuff truesize incorrect.

From: David Laight
Date: Fri May 23 2014 - 04:53:06 EST


From: Eric Dumazet
> On Thu, 2014-05-22 at 20:07 +0100, Jim Baxter wrote:
>
> >
> > I have been investigating a network issue with bursts of network traffic
> > over USB CDC-NCM, the issue is that the kernel is dropping packets
> > because sk_rcvqueues_full() returns true due to skb2->truesize is always
> > 32960 instead of SKB_TRUESIZE(skb2->len) which is about 1800.
> >
> > The code I am trying to fix is this code below, it is splitting a set of
> > multiple network packets compressed into a single 16k packet into
> > individual skb's and sending them up the network stack.
>
> if skb are allocated with 16k = 16384 bytes, adding the struct
> skb_shared_info overhead and rounding up to power of two gives 32768
> bytes.
>
> Chances to be able to allocate 32KB contiguous memory are slim after a
> while.
>
> I would set rx_max (rx_urb_size) to SKB_MAX_HEAD(0) so that you do not
> use high order allocations.
>
> What is the exact 'overhead' using ~4K instead of 16K exactly on this
> hardware ?

Many of the usb ethernet drivers have the same issue.

The hardware will put multiple ethernet frames into a single USB bulk data
message. To handle this the driver generates a URB that is (hopefully) long
enough for the longest USB message (typically 32k is assumed to be enough).
The URB that usb_net generated have the data in a linear skb - which then
has a large 'truesize'.

Since USB bulk data are terminated by a short fragment there is actually
no need for the URB be long enough for the full message. Provided the
URB are multiples of the USB message size (1k for USB 3) the message
can be received into multiple URB - the driver just has to be willing
to merge URB buffers (as well as split them) when generating the ethernet
frames.

What the driver needs to do us allocate URB with 2k (or 4k) buffers and
only allocate the skb when processing the receive data.
Unfortunately this is a major rework of usb_net.c

Note that some of the usb ethernet drivers allocate large skb then
lie about the truesize.

David