* [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
2008-05-26 7:42 [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Rusty Russell
@ 2008-05-26 7:48 ` Rusty Russell
2008-05-26 7:53 ` [PATCH 3/3] virtio: Use __skb_queue_purge() Rusty Russell
2008-05-27 11:01 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Mark McLoughlin
2008-05-27 11:06 ` [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Mark McLoughlin
2008-05-31 2:12 ` Jeff Garzik
2 siblings, 2 replies; 12+ messages in thread
From: Rusty Russell @ 2008-05-26 7:48 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, virtualization, Mark McLoughlin
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).
Cc: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
drivers/net/virtio_net.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff -r 1d1ff03de434 drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c Mon May 26 11:03:26 2008 +1000
+++ b/drivers/net/virtio_net.c Mon May 26 16:37:20 2008 +1000
@@ -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_info
return 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_d
skb_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");
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH 3/3] virtio: Use __skb_queue_purge()
2008-05-26 7:48 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Rusty Russell
@ 2008-05-26 7:53 ` Rusty Russell
2008-05-26 8:11 ` Wang Chen
2008-05-27 11:01 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Mark McLoughlin
1 sibling, 1 reply; 12+ messages in thread
From: Rusty Russell @ 2008-05-26 7:53 UTC (permalink / raw)
To: Jeff Garzik; +Cc: netdev, virtualization, Mark McLoughlin, Wang Chen
From: Wang Chen <wangchen@cn.fujitsu.com>
Use standard routine for queue purging.
Signed-off-by: Wang Chen <wangchen@cn.fujitsu.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
---
drivers/net/virtio_net.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index f926b5a..fe7cdf2 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -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);
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets.
2008-05-26 7:48 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Rusty Russell
2008-05-26 7:53 ` [PATCH 3/3] virtio: Use __skb_queue_purge() Rusty Russell
@ 2008-05-27 11:01 ` Mark McLoughlin
2008-05-28 4:59 ` Rusty Russell
1 sibling, 1 reply; 12+ messages in thread
From: Mark McLoughlin @ 2008-05-27 11:01 UTC (permalink / raw)
To: Rusty Russell; +Cc: Jeff Garzik, netdev, virtualization
On Mon, 2008-05-26 at 17:48 +1000, Rusty Russell wrote:
> 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).
...
> diff -r 1d1ff03de434 drivers/net/virtio_net.c
> --- a/drivers/net/virtio_net.c Mon May 26 11:03:26 2008 +1000
> +++ b/drivers/net/virtio_net.c Mon May 26 16:37:20 2008 +1000
...
> @@ -432,6 +452,8 @@ static int virtnet_probe(struct virtio_d
> skb_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.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-05-26 7:42 [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Rusty Russell
2008-05-26 7:48 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Rusty Russell
@ 2008-05-27 11:06 ` Mark McLoughlin
2008-05-29 6:34 ` Rusty Russell
2008-05-31 2:12 ` Jeff Garzik
2 siblings, 1 reply; 12+ messages in thread
From: Mark McLoughlin @ 2008-05-27 11:06 UTC (permalink / raw)
To: Rusty Russell; +Cc: Jeff Garzik, netdev, virtualization
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: Mark McLoughlin <markmc@redhat.com>
---
drivers/net/virtio_net.c | 20 ++++++++++----------
1 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index d50f4fe..30af05c 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -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;
}
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-05-27 11:06 ` [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Mark McLoughlin
@ 2008-05-29 6:34 ` Rusty Russell
2008-06-13 14:14 ` Mark McLoughlin
0 siblings, 1 reply; 12+ messages in thread
From: Rusty Russell @ 2008-05-29 6:34 UTC (permalink / raw)
To: Mark McLoughlin; +Cc: Jeff Garzik, netdev, virtualization
On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
> 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.
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 <markmc@redhat.com>
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: Mark McLoughlin <markmc@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (move last_xmit_skb = NULL)
---
drivers/net/virtio_net.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -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;
}
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-05-29 6:34 ` Rusty Russell
@ 2008-06-13 14:14 ` Mark McLoughlin
2008-06-13 19:57 ` Jeff Garzik
2008-06-14 7:39 ` Rusty Russell
0 siblings, 2 replies; 12+ messages in thread
From: Mark McLoughlin @ 2008-06-13 14:14 UTC (permalink / raw)
To: Rusty Russell; +Cc: Jeff Garzik, netdev, virtualization
On Thu, 2008-05-29 at 16:34 +1000, Rusty Russell wrote:
> On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
> > 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.
>
> 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 <markmc@redhat.com>
>
> 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.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-06-13 14:14 ` Mark McLoughlin
@ 2008-06-13 19:57 ` Jeff Garzik
2008-06-14 7:39 ` Rusty Russell
1 sibling, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2008-06-13 19:57 UTC (permalink / raw)
To: Mark McLoughlin; +Cc: Rusty Russell, netdev, virtualization
Mark McLoughlin wrote:
> On Thu, 2008-05-29 at 16:34 +1000, Rusty Russell wrote:
>> On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
>>> 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.
>> 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 <markmc@redhat.com>
>>
>> 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?
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-06-13 14:14 ` Mark McLoughlin
2008-06-13 19:57 ` Jeff Garzik
@ 2008-06-14 7:39 ` Rusty Russell
1 sibling, 0 replies; 12+ messages in thread
From: Rusty Russell @ 2008-06-14 7:39 UTC (permalink / raw)
To: Mark McLoughlin; +Cc: Jeff Garzik, netdev, virtualization
On Saturday 14 June 2008 00:14:00 Mark McLoughlin wrote:
> On Thu, 2008-05-29 at 16:34 +1000, Rusty Russell wrote:
> > On Tuesday 27 May 2008 21:06:26 Mark McLoughlin wrote:
> > > 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.
> >
> > 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 <markmc@redhat.com>
> >
> > 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.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug
2008-05-26 7:42 [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Rusty Russell
2008-05-26 7:48 ` [PATCH 2/3] virtio: fix delayed xmit of packet and freeing of old packets Rusty Russell
2008-05-27 11:06 ` [PATCH 1/3] virtio: fix virtio_net xmit of freed skb bug Mark McLoughlin
@ 2008-05-31 2:12 ` Jeff Garzik
2 siblings, 0 replies; 12+ messages in thread
From: Jeff Garzik @ 2008-05-31 2:12 UTC (permalink / raw)
To: Rusty Russell; +Cc: netdev, virtualization
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.
>
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> ---
> drivers/net/virtio_net.c | 14 +++++++++-----
> 1 file changed, 9 insertions(+), 5 deletions(-)
applied 1-2 (#3 was already applied)
^ permalink raw reply [flat|nested] 12+ messages in thread