virtio: fix virtio_net xmit of freed skb bug
Subsystems (4)
PATCH 1/3 virtio: fix virtio_net xmit of freed skb bug
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.
--- drivers/net/virtio_net.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/net/virtio_net.c +9 -5
@@ -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 ; }/* Put new one in send queue and do transmit */ -__skb_queue_head (&vi->send, skb); -if (xmit_skb (vi, skb) !=0 ) { - vi->last_xmit_skb = skb; - goto stop_queue; +if (likely (skb)) { +__skb_queue_head (&vi->send, skb); +if (xmit_skb (vi, skb) !=0 ) { + vi->last_xmit_skb = skb; + skb =NULL ; + goto stop_queue; + } } done: vi->svq->vq_ops->kick (vi->svq);
PATCH 2/3 virtio: fix delayed xmit of packet and freeing of old packets.
Because we cache the last failed-to-xmit packet, if there are no packets queued behind that one we may never send it (reproduced here as TCP stalls, "cured" by an outgoing ping).
--- drivers/net/virtio_net.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/net/virtio_net.c +22 -0
@@ -47,6 +47,9 @@ struct virtnet_info/* Number of input buffers, and max we've ever had. */ unsigned int num, max; +/* For cleaning up after transmission. */ +struct tasklet_struct tasklet; +/* Receive & send queues. */ struct sk_buff_head recv;struct sk_buff_head send;
@@ -68,8 +71,13 @@ static void skb_xmit_done(struct virtque/* Suppress further interrupts. */ svq->vq_ops->disable_cb (svq); +/* We were waiting for more output buffers. */ netif_wake_queue (vi->dev); + +/* Make sure we re-xmit last_xmit_skb: if there are no more packets +* queued, start_xmit won't be called. */ +tasklet_schedule (&vi->tasklet); } static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -278,6 +286,18 @@ static int xmit_skb(struct virtnet_inforeturn vi->svq->vq_ops->add_buf (vi->svq, sg, num,0 , skb); } +static void xmit_tasklet (unsigned long data) +{ +struct virtnet_info *vi = (void *)data; + +netif_tx_lock_bh (vi->dev); +if (vi->last_xmit_skb &&xmit_skb (vi, vi->last_xmit_skb) ==0 ) { + vi->svq->vq_ops->kick (vi->svq); + vi->last_xmit_skb =NULL ; + } +netif_tx_unlock_bh (vi->dev); +} +static int start_xmit (struct sk_buff *skb,struct net_device *dev) {struct virtnet_info *vi =netdev_priv (dev);
@@ -432,6 +452,8 @@ static int virtnet_probe(struct virtio_dskb_queue_head_init (&vi->recv);skb_queue_head_init (&vi->send); +tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);if (err) {pr_debug ("virtio_net: registering device failed\n" );
PATCH 2/3 virtio: fix delayed xmit of packet and freeing of old packets.
In reply to Rusty RussellBecause we cache the last failed-to-xmit packet, if there are no packets queued behind that one we may never send it (reproduced here as TCP stalls, "cured" by an outgoing ping).
--- drivers/net/virtio_net.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
drivers/net/virtio_net.c +22 -0
@@ -47,6 +47,9 @@ struct virtnet_info/* Number of input buffers, and max we've ever had. */ unsigned int num, max; +/* For cleaning up after transmission. */ +struct tasklet_struct tasklet; +/* Receive & send queues. */ struct sk_buff_head recv;struct sk_buff_head send;
@@ -68,8 +71,13 @@ static void skb_xmit_done(struct virtque/* Suppress further interrupts. */ svq->vq_ops->disable_cb (svq); +/* We were waiting for more output buffers. */ netif_wake_queue (vi->dev); + +/* Make sure we re-xmit last_xmit_skb: if there are no more packets +* queued, start_xmit won't be called. */ +tasklet_schedule (&vi->tasklet); } static void receive_skb(struct net_device *dev, struct sk_buff *skb,
@@ -278,6 +286,18 @@ static int xmit_skb(struct virtnet_inforeturn vi->svq->vq_ops->add_buf (vi->svq, sg, num,0 , skb); } +static void xmit_tasklet (unsigned long data) +{ +struct virtnet_info *vi = (void *)data; + +netif_tx_lock_bh (vi->dev); +if (vi->last_xmit_skb &&xmit_skb (vi, vi->last_xmit_skb) ==0 ) { + vi->svq->vq_ops->kick (vi->svq); + vi->last_xmit_skb =NULL ; + } +netif_tx_unlock_bh (vi->dev); +} +static int start_xmit (struct sk_buff *skb,struct net_device *dev) {struct virtnet_info *vi =netdev_priv (dev);
@@ -432,6 +452,8 @@ static int virtnet_probe(struct virtio_dskb_queue_head_init (&vi->recv);skb_queue_head_init (&vi->send); +tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);if (err) {pr_debug ("virtio_net: registering device failed\n" );
PATCH 3/3 virtio: Use __skb_queue_purge()
From: Wang Chen <[email protected]>
Use standard routine for queue purging.
--- drivers/net/virtio_net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/virtio_net.c +1 -2
@@ -470,8 +470,7 @@ static void virtnet_remove(struct virtio_device *vdev)kfree_skb (skb); vi->num--; } -while ((skb =__skb_dequeue (&vi->send)) !=NULL ) -kfree_skb (skb); +__skb_queue_purge (&vi->send);BUG_ON (vi->num !=0 );
PATCH 3/3 virtio: Use __skb_queue_purge()
In reply to Rusty RussellFrom: Wang Chen <[email protected]>
Use standard routine for queue purging.
--- drivers/net/virtio_net.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/virtio_net.c +1 -2
@@ -470,8 +470,7 @@ static void virtnet_remove(struct virtio_device *vdev)kfree_skb (skb); vi->num--; } -while ((skb =__skb_dequeue (&vi->send)) !=NULL ) -kfree_skb (skb); +__skb_queue_purge (&vi->send);BUG_ON (vi->num !=0 );
Re: [PATCH 3/3] virtio: Use __skb_queue_purge()
Rusty Russell said the following on 2008-5-26 15:53:
Quoted 6 lines
From: Wang Chen <[email protected]>
Use standard routine for queue purging.
Signed-off-by Wang Chen <[email protected]>Signed-off-by Rusty Russell <[email protected]>
Rusty, Jeff has applied this one and David has merged it and send a pull request to Linus.
Thanks.
Re: [PATCH 3/3] virtio: Use __skb_queue_purge()
In reply to Rusty RussellRusty Russell said the following on 2008-5-26 15:53:
Quoted 6 lines
From: Wang Chen <[email protected]>
Use standard routine for queue purging.
Signed-off-by Wang Chen <[email protected]>Signed-off-by Rusty Russell <[email protected]>
Rusty, Jeff has applied this one and David has merged it and send a pull request to Linus.
Thanks.
Re: [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
Because we cache the last failed-to-xmit packet, if there are no packets queued behind that one we may never send it (reproduced here as TCP stalls, "cured" by an outgoing ping).
...
Quoted 3 lines
diff -r
1d1ff03de434drivers/net/virtio_net.cdrivers/net/virtio_net.c +0
-0
...
drivers/net/virtio_net.c static int virtnet_probe(struct virtio_d · line 457
Quoted 7 lines
drivers/net/virtio_net.c +2
-0@@ -432,6 +452,8 @@ static int virtnet_probe(struct virtio_dskb_queue_head_init (&vi->recv);skb_queue_head_init (&vi->send); +tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);
Missing a tasklet_kill() in virtnet_remove() ?
Cheers,
Mark.
Re: [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
In reply to Rusty RussellQuoted 3 lines · Rusty Russell
Because we cache the last failed-to-xmit packet, if there are no packets queued behind that one we may never send it (reproduced here as TCP stalls, "cured" by an outgoing ping).
...
Quoted 3 lines
diff -r
1d1ff03de434drivers/net/virtio_net.cdrivers/net/virtio_net.c +0
-0
...
drivers/net/virtio_net.c static int virtnet_probe(struct virtio_d · line 457
Quoted 7 lines
drivers/net/virtio_net.c +2
-0@@ -432,6 +452,8 @@ static int virtnet_probe(struct virtio_dskb_queue_head_init (&vi->recv);skb_queue_head_init (&vi->send); +tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);
Missing a tasklet_kill() in virtnet_remove() ?
Cheers,
Mark.
Re: [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
Quoted 8 lines · On Tuesday 27 May 2008 21:01:08 Mark McLoughlin wrote:
Quoted 1 line · Rusty Russell
diff -r
1d1ff03de434drivers/net/virtio_net.c...
drivers/net/virtio_net.c static int virtnet_probe(struct virtio_d · line 457
Quoted 3 lines
drivers/net/virtio_net.c +2
-0+tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);Missing a
tasklet_kill()invirtnet_remove()?
Thanks Mark! Added.
Nice spotting,
Rusty.
Re: [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
In reply to Mark McLoughlinQuoted 8 lines · On Tuesday 27 May 2008 21:01:08 Mark McLoughlin wrote:
Quoted 1 line · Rusty Russell
diff -r
1d1ff03de434drivers/net/virtio_net.c...
drivers/net/virtio_net.c static int virtnet_probe(struct virtio_d · line 457
Quoted 3 lines
drivers/net/virtio_net.c +2
-0+tasklet_init (&vi->tasklet, xmit_tasklet, (unsigned long )vi); + err =register_netdev (dev);Missing a
tasklet_kill()invirtnet_remove()?
Thanks Mark! Added.
Nice spotting,
Rusty.
Quoted 6 lines · Rusty Russell
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.
...
Quoted 7 lines
diff -r
564237b31993drivers/net/virtio_net.cdrivers/net/virtio_net.c +0
-0@@ -287,21 +287,25 @@ again:free_old_xmit_skbs (vi);/* If we has a buffer left over from last time, send it now. */
drivers/net/virtio_net.c again: · line 298
Quoted 10 lines
drivers/net/virtio_net.c +2
-1-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.
--- drivers/net/virtio_net.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
drivers/net/virtio_net.c +10 -10
@@ -287,16 +287,11 @@ again:free_old_xmit_skbs (vi);/* If we has a buffer left over from last time, send it now. */ -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 ; - } +if (unlikely (vi->last_xmit_skb) && +xmit_skb (vi, vi->last_xmit_skb) !=0 ) + goto stop_queue; + + vi->last_xmit_skb =NULL ;/* Put new one in send queue and do transmit */ if (likely (skb)) {
@@ -322,6 +317,11 @@ stop_queue:netif_start_queue (dev); goto again; } +if (skb) { +/* Drop this skb: we only queue one. */ + vi->dev->stats.tx_dropped++; +kfree_skb (skb); + } goto done; }
Quoted 6 lines · Rusty Russell
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.
...
Quoted 7 lines
diff -r
564237b31993drivers/net/virtio_net.cdrivers/net/virtio_net.c +0
-0@@ -287,21 +287,25 @@ again:free_old_xmit_skbs (vi);/* If we has a buffer left over from last time, send it now. */
drivers/net/virtio_net.c again: · line 298
Quoted 10 lines
drivers/net/virtio_net.c +2
-1-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.
--- drivers/net/virtio_net.c | 20 ++++++++++---------- 1 files changed, 10 insertions(+), 10 deletions(-)
drivers/net/virtio_net.c +10 -10
@@ -287,16 +287,11 @@ again:free_old_xmit_skbs (vi);/* If we has a buffer left over from last time, send it now. */ -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 ; - } +if (unlikely (vi->last_xmit_skb) && +xmit_skb (vi, vi->last_xmit_skb) !=0 ) + goto stop_queue; + + vi->last_xmit_skb =NULL ;/* Put new one in send queue and do transmit */ if (likely (skb)) {
@@ -322,6 +317,11 @@ stop_queue:netif_start_queue (dev); goto again; } +if (skb) { +/* Drop this skb: we only queue one. */ + vi->dev->stats.tx_dropped++; +kfree_skb (skb); + } goto done; }
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the vi->last_xmit_skb = NULL; under the branch:
Subject: [PATCH] virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
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.
--- drivers/net/virtio_net.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/virtio_net.c +6 -6
@@ -308,13 +308,8 @@ again:/* If we has a buffer left over from last time, send it now. */ 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 ; +if (xmit_skb (vi, vi->last_xmit_skb) !=0 ) goto stop_queue; - } vi->last_xmit_skb =NULL ; }
@@ -341,6 +336,11 @@ stop_queue: vi->svq->vq_ops->disable_cb (vi->svq);netif_start_queue (dev); goto again; + } +if (skb) { +/* Drop this skb: we only queue one. */ + vi->dev->stats.tx_dropped++; +kfree_skb (skb); } goto done; }
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the vi->last_xmit_skb = NULL; under the branch:
Subject: [PATCH] virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
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.
--- drivers/net/virtio_net.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/virtio_net.c +6 -6
@@ -308,13 +308,8 @@ again:/* If we has a buffer left over from last time, send it now. */ 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 ; +if (xmit_skb (vi, vi->last_xmit_skb) !=0 ) goto stop_queue; - } vi->last_xmit_skb =NULL ; }
@@ -341,6 +336,11 @@ stop_queue: vi->svq->vq_ops->disable_cb (vi->svq);netif_start_queue (dev); goto again; + } +if (skb) { +/* Drop this skb: we only queue one. */ + vi->dev->stats.tx_dropped++; +kfree_skb (skb); } goto done; }
Quoted 18 lines · Rusty Russell
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
Cheers,
Mark.
Quoted 18 lines · Rusty Russell
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
Cheers,
Mark.
Quoted 18 lines · Mark McLoughlin
Quoted 17 lines · Rusty Russell
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 8 lines
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
can someone resend?
Quoted 18 lines · Mark McLoughlin
Quoted 17 lines · Rusty Russell
Quoted 7 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 6 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 8 lines
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
can someone resend?
Quoted 21 lines · On Saturday 14 June 2008 00:14:00 Mark McLoughlin wrote:
Quoted 20 lines · Rusty Russell
Quoted 8 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 7 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 8 lines
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
Good catch. Looks like it got folded, but pre-folded version got merged. Sorry, I've restored it to my series.
Thanks,
Rusty.
Quoted 21 lines · On Saturday 14 June 2008 00:14:00 Mark McLoughlin wrote:
Quoted 20 lines · Rusty Russell
Quoted 8 lines · On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
Quoted 7 lines · Rusty Russell
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.
Great! It's a corner case, but it's no more complicated to do it your way.
Minor mod, I find it clearer to have the
vi->last_xmit_skb= NULL; under the branch:Subject: [PATCH]
virtio_net: Delay dropping tx skbs
Date: Tue, 27 May 2008 12:06:26 +0100
From: Mark McLoughlin <[email protected]>
Quoted 8 lines
Quoted 6 lines
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.
Hmm, we lost this one somewhere along the way ...
Good catch. Looks like it got folded, but pre-folded version got merged. Sorry, I've restored it to my series.
Thanks,
Rusty.
Quoted 11 lines · Rusty Russell
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.
Signed-off-by Rusty Russell <[email protected]>--- drivers/net/virtio_net.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
applied 1-2 (#3 was already applied)
Quoted 11 lines · Rusty Russell
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.
Signed-off-by Rusty Russell <[email protected]>--- drivers/net/virtio_net.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
applied 1-2 (#3 was already applied)