• Mark McLoughlin's avatar
    virtio: fix virtio_net xmit of freed skb bug · 9953ca6c
    Mark McLoughlin authored
    On Mon, 2008-05-26 at 17:42 +1000, Rusty Russell wrote:
    > If we fail to transmit a packet, we assume the queue is full and put
    > the skb into last_xmit_skb.  However, if more space frees up before we
    > xmit it, we loop, and the result can be transmitting the same skb twice.
    >
    > Fix is simple: set skb to NULL if we've used it in some way, and check
    > before sending.
    ...
    > diff -r 564237b31993 drivers/net/virtio_net.c
    > --- a/drivers/net/virtio_net.c	Mon May 19 12:22:00 2008 +1000
    > +++ b/drivers/net/virtio_net.c	Mon May 19 12:24:58 2008 +1000
    > @@ -287,21 +287,25 @@ again:
    >  	free_old_xmit_skbs(vi);
    >
    >  	/* If we has a buffer left over from last time, send it now. */
    > -	if (vi->last_xmit_skb) {
    > +	if (unlikely(vi->last_xmit_skb)) {
    >  		if (xmit_skb(vi, vi->last_xmit_skb) != 0) {
    >  			/* Drop this skb: we only queue one. */
    >  			vi->dev->stats.tx_dropped++;
    >  			kfree_skb(skb);
    > +			skb = NULL;
    >  			goto stop_queue;
    >  		}
    >  		vi->last_xmit_skb = NULL;
    
    With this, may drop an skb and then later in the function discover that
    we could have sent it after all. Poor wee skb :)
    
    How about the incremental patch below?
    
    Cheers,
    Mark.
    
    Subject: [PATCH] virtio_net: Delay dropping tx skbs
    
    Currently we drop the skb in start_xmit() if we have a
    queued buffer and fail to transmit it.
    
    However, if we delay dropping it until we've stopped the
    queue and enabled the tx notification callback, then there
    is a chance space might become available for it.
    Signed-off-by: default avatarMark McLoughlin <markmc@redhat.com>
    Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
    9953ca6c
virtio_net.c 15 KB