All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jason Wang <jasowang@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: netdev@vger.kernel.org, qemu-devel@nongnu.org,
	linux-kernel@vger.kernel.org, Amit Shah <amit.shah@redhat.com>,
	virtualization@lists.linux-foundation.org, davem@davemloft.net
Subject: Re: [V6 PATCH] virtio-net: send gratuitous packets when needed
Date: Thu, 05 Apr 2012 13:56:15 +0800	[thread overview]
Message-ID: <4F7D33FF.2060304@redhat.com> (raw)
In-Reply-To: <20120404074937.GA22658@redhat.com>

On 04/04/2012 03:49 PM, Michael S. Tsirkin wrote:
> On Wed, Mar 28, 2012 at 01:44:28PM +0800, Jason Wang wrote:
>> As hypervior does not have the knowledge of guest network configuration, it's
>> better to ask guest to send gratuitous packets when needed.
>>
>> Guest tests VIRTIO_NET_S_ANNOUNCE bit during config change interrupt and when it
>> is set, a workqueue is scheduled to send gratuitous packet through
>> NETDEV_NOTIFY_PEERS. This feature is negotiated through bit
>> VIRTIO_NET_F_GUEST_ANNOUNCE.
>>
>> Changes from v5:
>> - notify the chain before acking the link annoucement
>> - ack the link announcement notification through control vq
>>
>> Changes from v4:
>> - typos
>> - handle workqueue unconditionally
>> - move VIRTIO_NET_S_ANNOUNCE to bit 8 to separate rw bits from ro bits
>>
>> Changes from v3:
>> - cancel the workqueue during freeze
>>
>> Changes from v2:
>> - fix the race between unregister_dev() and workqueue
>>
>> Signed-off-by: Jason Wang<jasowang@redhat.com>
> I think this needs some fixes. See below.
> Thanks.
>
>> ---
>>   drivers/net/virtio_net.c   |   32 +++++++++++++++++++++++++++++++-
>>   include/linux/virtio_net.h |   13 +++++++++++++
>>   2 files changed, 44 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>> index 4880aa8..0f60da7 100644
>> --- a/drivers/net/virtio_net.c
>> +++ b/drivers/net/virtio_net.c
>> @@ -72,6 +72,9 @@ struct virtnet_info {
>>   	/* Work struct for refilling if we run low on memory. */
>>   	struct delayed_work refill;
>>
>> +	/* Work struct for sending gratuitous packets. */
> A bit confusing: it does not send anything itself.
> A better comment 'for announcing the existence of device
> on the network'.
>
>> +	struct work_struct announce;
>> +
>>   	/* Chain pages by the private ptr. */
>>   	struct page *pages;
>>
>> @@ -781,12 +784,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
>>   	return status == VIRTIO_NET_OK;
>>   }
>>
>> +static void virtnet_ack_link_announce(struct virtnet_info *vi)
>> +{
>> +	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
>> +				  VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL,
>> +				  0, 0)) {
> This can run in parallel with other commands. That's pretty bad -
> will corrupt the cvq.
> Take rtnl lock around calls to this function?

It's only used by callbacks of netif_notify_peers(), so rtnl lock have 
already been hold. Add a comment to clarify this?
>> +		dev_warn(&vi->dev->dev, "Failed to ack link nnounce.\n");
> announce

Sorry for the typos, would double check in the future.
>> +	}
> Better to drop {} around a single statement.
>
>> +}
>> +
>> +static void announce_work(struct work_struct *work)
>> +{
>> +	struct virtnet_info *vi = container_of(work, struct virtnet_info,
>> +					       announce);
>> +	netif_notify_peers(vi->dev);
>> +	virtnet_ack_link_announce(vi);
>> +}
>> +
>>   static int virtnet_close(struct net_device *dev)
>>   {
>>   	struct virtnet_info *vi = netdev_priv(dev);
>>
>>   	/* Make sure refill_work doesn't re-enable napi! */
>>   	cancel_delayed_work_sync(&vi->refill);
>> +	cancel_work_sync(&vi->announce);
> I think that a config change event can trigger after this point,
> so cancel here won't be effective. But why do it here?
> virtnet_remove not a better place? We can do it
> after remove_vq_common.

Sure.
>>   	napi_disable(&vi->napi);
>>
>>   	return 0;
>> @@ -962,11 +983,17 @@ static void virtnet_update_status(struct virtnet_info *vi)
>>   		return;
>>
>>   	/* Ignore unknown (future) status bits */
>> -	v&= VIRTIO_NET_S_LINK_UP;
>> +	v&= VIRTIO_NET_S_LINK_UP | VIRTIO_NET_S_ANNOUNCE;
> The announce bit in vi->status is always clear,
> so this is IMO confusing. I would do:
>
> 	if (v&  VIRTIO_NET_S_ANNOUNCE) {
> 		schedule
> 	}
>
> 	v&= VIRTIO_NET_S_LINK_UP;
>
> and the rest of the logic is not necessary then.
>
> Also, this might run extra ack announce commands after
> VIRTIO_NET_S_ANNOUNCE bit is clear. The spec
> isn't clear on whether this is legal.
>
> It would be very hard to fix this, so let's add a comment
> stating that it's legal, and clarify the spec
> in any case.

How about delay the clearing of VIRTIO_NET_S_ANNOUNCE bit in the 
workqueue and protect the updating with 
spinlock_irqsave()/spinloc_irqrestore()? Then later notification would 
be suppressed if the sending is not completed.
>>
>>   	if (vi->status == v)
>>   		return;
>>
>> +	if (v&  VIRTIO_NET_S_ANNOUNCE) {
>> +		v&= ~VIRTIO_NET_S_ANNOUNCE;
>> +		if (v&  VIRTIO_NET_S_LINK_UP)
>> +			schedule_work(&vi->announce);
> I think we really want an nrt wq here - if this triggers
> multiple times there's no good reason to try and run
> the ack command many times in parallel.

Yes.
>> +	}
>> +
>>   	vi->status = v;
>>
>>   	if (vi->status&  VIRTIO_NET_S_LINK_UP) {
>
>> @@ -1076,6 +1103,7 @@ static int virtnet_probe(struct virtio_device *vdev)
>>   		goto free;
>>
>>   	INIT_DELAYED_WORK(&vi->refill, refill_work);
>> +	INIT_WORK(&vi->announce, announce_work);
>>   	sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
>>   	sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
>>
>> @@ -1187,6 +1215,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
>>   	virtqueue_disable_cb(vi->svq);
>>   	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
>>   		virtqueue_disable_cb(vi->cvq);
>> +	cancel_work_sync(&vi->announce);
> A config change event can trigger after this point,
> so cancel here won't be effective.
> Possibly, we need state like config_enable in the block
> device.

Probably needed.
>
> Also, what exactly will happen on suspend?
> As we reset, ANNOUCE bit will be clear so -
> do we forget to announce? Probably not good ...

This problem should be the same as normal suspending/resuming, if user 
want to announce the link they should use arp_notify instead.
>
>>
>>   	netif_device_detach(vi->dev);
>>   	cancel_delayed_work_sync(&vi->refill);
>> @@ -1233,6 +1262,7 @@ static unsigned int features[] = {
>>   	VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
>>   	VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
>>   	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
>> +	VIRTIO_NET_F_GUEST_ANNOUNCE,
>>   };
>>
>>   static struct virtio_driver virtio_net_driver = {
>> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
>> index 970d5a2..383e8a0 100644
>> --- a/include/linux/virtio_net.h
>> +++ b/include/linux/virtio_net.h
>> @@ -49,8 +49,10 @@
>>   #define VIRTIO_NET_F_CTRL_RX	18	/* Control channel RX mode support */
>>   #define VIRTIO_NET_F_CTRL_VLAN	19	/* Control channel VLAN filtering */
>>   #define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
>> +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21  /* Guest can send gratituous packet */
> Rusty aligned the comments using tabs so let's do it here too?
> A better comment 'can announce device on the network'.
>
>>
>>   #define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
>> +#define VIRTIO_NET_S_ANNOUNCE   2	/* Announcement is needed */
> why 3 spaces before the value here?
>
>>
>>   struct virtio_net_config {
>>   	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
>> @@ -152,4 +154,15 @@ struct virtio_net_ctrl_mac {
>>    #define VIRTIO_NET_CTRL_VLAN_ADD             0
>>    #define VIRTIO_NET_CTRL_VLAN_DEL             1
>>
>> +/*
>> + * Control link announce acknowledgement
>> + *
>> + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
>> + * driver has recevied the notification and device would clear the
> s/recevied/received/
>
> A bit clearer to replace 'and' with ; here.
>
>> + * VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
> s/filed/field/
> s/received/receives/
>
>> + * this command.
>> + */
>> +#define VIRTIO_NET_CTRL_ANNOUNCE       3
>> + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
>> +
>>   #endif /* _LINUX_VIRTIO_NET_H */
>>
>> _______________________________________________
>> Virtualization mailing list
>> Virtualization@lists.linux-foundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/virtualization

WARNING: multiple messages have this Message-ID (diff)
From: Jason Wang <jasowang@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: netdev@vger.kernel.org, rusty@rustcorp.com.au,
	linux-kernel@vger.kernel.org,
	virtualization@lists.linux-foundation.org, davem@davemloft.net,
	qemu-devel@nongnu.org, Amit Shah <amit.shah@redhat.com>
Subject: Re: [V6 PATCH] virtio-net: send gratuitous packets when needed
Date: Thu, 05 Apr 2012 13:56:15 +0800	[thread overview]
Message-ID: <4F7D33FF.2060304@redhat.com> (raw)
In-Reply-To: <20120404074937.GA22658@redhat.com>

On 04/04/2012 03:49 PM, Michael S. Tsirkin wrote:
> On Wed, Mar 28, 2012 at 01:44:28PM +0800, Jason Wang wrote:
>> As hypervior does not have the knowledge of guest network configuration, it's
>> better to ask guest to send gratuitous packets when needed.
>>
>> Guest tests VIRTIO_NET_S_ANNOUNCE bit during config change interrupt and when it
>> is set, a workqueue is scheduled to send gratuitous packet through
>> NETDEV_NOTIFY_PEERS. This feature is negotiated through bit
>> VIRTIO_NET_F_GUEST_ANNOUNCE.
>>
>> Changes from v5:
>> - notify the chain before acking the link annoucement
>> - ack the link announcement notification through control vq
>>
>> Changes from v4:
>> - typos
>> - handle workqueue unconditionally
>> - move VIRTIO_NET_S_ANNOUNCE to bit 8 to separate rw bits from ro bits
>>
>> Changes from v3:
>> - cancel the workqueue during freeze
>>
>> Changes from v2:
>> - fix the race between unregister_dev() and workqueue
>>
>> Signed-off-by: Jason Wang<jasowang@redhat.com>
> I think this needs some fixes. See below.
> Thanks.
>
>> ---
>>   drivers/net/virtio_net.c   |   32 +++++++++++++++++++++++++++++++-
>>   include/linux/virtio_net.h |   13 +++++++++++++
>>   2 files changed, 44 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>> index 4880aa8..0f60da7 100644
>> --- a/drivers/net/virtio_net.c
>> +++ b/drivers/net/virtio_net.c
>> @@ -72,6 +72,9 @@ struct virtnet_info {
>>   	/* Work struct for refilling if we run low on memory. */
>>   	struct delayed_work refill;
>>
>> +	/* Work struct for sending gratuitous packets. */
> A bit confusing: it does not send anything itself.
> A better comment 'for announcing the existence of device
> on the network'.
>
>> +	struct work_struct announce;
>> +
>>   	/* Chain pages by the private ptr. */
>>   	struct page *pages;
>>
>> @@ -781,12 +784,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
>>   	return status == VIRTIO_NET_OK;
>>   }
>>
>> +static void virtnet_ack_link_announce(struct virtnet_info *vi)
>> +{
>> +	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
>> +				  VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL,
>> +				  0, 0)) {
> This can run in parallel with other commands. That's pretty bad -
> will corrupt the cvq.
> Take rtnl lock around calls to this function?

It's only used by callbacks of netif_notify_peers(), so rtnl lock have 
already been hold. Add a comment to clarify this?
>> +		dev_warn(&vi->dev->dev, "Failed to ack link nnounce.\n");
> announce

Sorry for the typos, would double check in the future.
>> +	}
> Better to drop {} around a single statement.
>
>> +}
>> +
>> +static void announce_work(struct work_struct *work)
>> +{
>> +	struct virtnet_info *vi = container_of(work, struct virtnet_info,
>> +					       announce);
>> +	netif_notify_peers(vi->dev);
>> +	virtnet_ack_link_announce(vi);
>> +}
>> +
>>   static int virtnet_close(struct net_device *dev)
>>   {
>>   	struct virtnet_info *vi = netdev_priv(dev);
>>
>>   	/* Make sure refill_work doesn't re-enable napi! */
>>   	cancel_delayed_work_sync(&vi->refill);
>> +	cancel_work_sync(&vi->announce);
> I think that a config change event can trigger after this point,
> so cancel here won't be effective. But why do it here?
> virtnet_remove not a better place? We can do it
> after remove_vq_common.

Sure.
>>   	napi_disable(&vi->napi);
>>
>>   	return 0;
>> @@ -962,11 +983,17 @@ static void virtnet_update_status(struct virtnet_info *vi)
>>   		return;
>>
>>   	/* Ignore unknown (future) status bits */
>> -	v&= VIRTIO_NET_S_LINK_UP;
>> +	v&= VIRTIO_NET_S_LINK_UP | VIRTIO_NET_S_ANNOUNCE;
> The announce bit in vi->status is always clear,
> so this is IMO confusing. I would do:
>
> 	if (v&  VIRTIO_NET_S_ANNOUNCE) {
> 		schedule
> 	}
>
> 	v&= VIRTIO_NET_S_LINK_UP;
>
> and the rest of the logic is not necessary then.
>
> Also, this might run extra ack announce commands after
> VIRTIO_NET_S_ANNOUNCE bit is clear. The spec
> isn't clear on whether this is legal.
>
> It would be very hard to fix this, so let's add a comment
> stating that it's legal, and clarify the spec
> in any case.

How about delay the clearing of VIRTIO_NET_S_ANNOUNCE bit in the 
workqueue and protect the updating with 
spinlock_irqsave()/spinloc_irqrestore()? Then later notification would 
be suppressed if the sending is not completed.
>>
>>   	if (vi->status == v)
>>   		return;
>>
>> +	if (v&  VIRTIO_NET_S_ANNOUNCE) {
>> +		v&= ~VIRTIO_NET_S_ANNOUNCE;
>> +		if (v&  VIRTIO_NET_S_LINK_UP)
>> +			schedule_work(&vi->announce);
> I think we really want an nrt wq here - if this triggers
> multiple times there's no good reason to try and run
> the ack command many times in parallel.

Yes.
>> +	}
>> +
>>   	vi->status = v;
>>
>>   	if (vi->status&  VIRTIO_NET_S_LINK_UP) {
>
>> @@ -1076,6 +1103,7 @@ static int virtnet_probe(struct virtio_device *vdev)
>>   		goto free;
>>
>>   	INIT_DELAYED_WORK(&vi->refill, refill_work);
>> +	INIT_WORK(&vi->announce, announce_work);
>>   	sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
>>   	sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
>>
>> @@ -1187,6 +1215,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
>>   	virtqueue_disable_cb(vi->svq);
>>   	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
>>   		virtqueue_disable_cb(vi->cvq);
>> +	cancel_work_sync(&vi->announce);
> A config change event can trigger after this point,
> so cancel here won't be effective.
> Possibly, we need state like config_enable in the block
> device.

Probably needed.
>
> Also, what exactly will happen on suspend?
> As we reset, ANNOUCE bit will be clear so -
> do we forget to announce? Probably not good ...

This problem should be the same as normal suspending/resuming, if user 
want to announce the link they should use arp_notify instead.
>
>>
>>   	netif_device_detach(vi->dev);
>>   	cancel_delayed_work_sync(&vi->refill);
>> @@ -1233,6 +1262,7 @@ static unsigned int features[] = {
>>   	VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
>>   	VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
>>   	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
>> +	VIRTIO_NET_F_GUEST_ANNOUNCE,
>>   };
>>
>>   static struct virtio_driver virtio_net_driver = {
>> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
>> index 970d5a2..383e8a0 100644
>> --- a/include/linux/virtio_net.h
>> +++ b/include/linux/virtio_net.h
>> @@ -49,8 +49,10 @@
>>   #define VIRTIO_NET_F_CTRL_RX	18	/* Control channel RX mode support */
>>   #define VIRTIO_NET_F_CTRL_VLAN	19	/* Control channel VLAN filtering */
>>   #define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
>> +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21  /* Guest can send gratituous packet */
> Rusty aligned the comments using tabs so let's do it here too?
> A better comment 'can announce device on the network'.
>
>>
>>   #define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
>> +#define VIRTIO_NET_S_ANNOUNCE   2	/* Announcement is needed */
> why 3 spaces before the value here?
>
>>
>>   struct virtio_net_config {
>>   	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
>> @@ -152,4 +154,15 @@ struct virtio_net_ctrl_mac {
>>    #define VIRTIO_NET_CTRL_VLAN_ADD             0
>>    #define VIRTIO_NET_CTRL_VLAN_DEL             1
>>
>> +/*
>> + * Control link announce acknowledgement
>> + *
>> + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
>> + * driver has recevied the notification and device would clear the
> s/recevied/received/
>
> A bit clearer to replace 'and' with ; here.
>
>> + * VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
> s/filed/field/
> s/received/receives/
>
>> + * this command.
>> + */
>> +#define VIRTIO_NET_CTRL_ANNOUNCE       3
>> + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
>> +
>>   #endif /* _LINUX_VIRTIO_NET_H */
>>
>> _______________________________________________
>> Virtualization mailing list
>> Virtualization@lists.linux-foundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/virtualization


WARNING: multiple messages have this Message-ID (diff)
From: Jason Wang <jasowang@redhat.com>
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: netdev@vger.kernel.org, rusty@rustcorp.com.au,
	qemu-devel@nongnu.org, linux-kernel@vger.kernel.org,
	Amit Shah <amit.shah@redhat.com>,
	virtualization@lists.linux-foundation.org, davem@davemloft.net
Subject: Re: [Qemu-devel] [V6 PATCH] virtio-net: send gratuitous packets when needed
Date: Thu, 05 Apr 2012 13:56:15 +0800	[thread overview]
Message-ID: <4F7D33FF.2060304@redhat.com> (raw)
In-Reply-To: <20120404074937.GA22658@redhat.com>

On 04/04/2012 03:49 PM, Michael S. Tsirkin wrote:
> On Wed, Mar 28, 2012 at 01:44:28PM +0800, Jason Wang wrote:
>> As hypervior does not have the knowledge of guest network configuration, it's
>> better to ask guest to send gratuitous packets when needed.
>>
>> Guest tests VIRTIO_NET_S_ANNOUNCE bit during config change interrupt and when it
>> is set, a workqueue is scheduled to send gratuitous packet through
>> NETDEV_NOTIFY_PEERS. This feature is negotiated through bit
>> VIRTIO_NET_F_GUEST_ANNOUNCE.
>>
>> Changes from v5:
>> - notify the chain before acking the link annoucement
>> - ack the link announcement notification through control vq
>>
>> Changes from v4:
>> - typos
>> - handle workqueue unconditionally
>> - move VIRTIO_NET_S_ANNOUNCE to bit 8 to separate rw bits from ro bits
>>
>> Changes from v3:
>> - cancel the workqueue during freeze
>>
>> Changes from v2:
>> - fix the race between unregister_dev() and workqueue
>>
>> Signed-off-by: Jason Wang<jasowang@redhat.com>
> I think this needs some fixes. See below.
> Thanks.
>
>> ---
>>   drivers/net/virtio_net.c   |   32 +++++++++++++++++++++++++++++++-
>>   include/linux/virtio_net.h |   13 +++++++++++++
>>   2 files changed, 44 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
>> index 4880aa8..0f60da7 100644
>> --- a/drivers/net/virtio_net.c
>> +++ b/drivers/net/virtio_net.c
>> @@ -72,6 +72,9 @@ struct virtnet_info {
>>   	/* Work struct for refilling if we run low on memory. */
>>   	struct delayed_work refill;
>>
>> +	/* Work struct for sending gratuitous packets. */
> A bit confusing: it does not send anything itself.
> A better comment 'for announcing the existence of device
> on the network'.
>
>> +	struct work_struct announce;
>> +
>>   	/* Chain pages by the private ptr. */
>>   	struct page *pages;
>>
>> @@ -781,12 +784,30 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
>>   	return status == VIRTIO_NET_OK;
>>   }
>>
>> +static void virtnet_ack_link_announce(struct virtnet_info *vi)
>> +{
>> +	if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE,
>> +				  VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL,
>> +				  0, 0)) {
> This can run in parallel with other commands. That's pretty bad -
> will corrupt the cvq.
> Take rtnl lock around calls to this function?

It's only used by callbacks of netif_notify_peers(), so rtnl lock have 
already been hold. Add a comment to clarify this?
>> +		dev_warn(&vi->dev->dev, "Failed to ack link nnounce.\n");
> announce

Sorry for the typos, would double check in the future.
>> +	}
> Better to drop {} around a single statement.
>
>> +}
>> +
>> +static void announce_work(struct work_struct *work)
>> +{
>> +	struct virtnet_info *vi = container_of(work, struct virtnet_info,
>> +					       announce);
>> +	netif_notify_peers(vi->dev);
>> +	virtnet_ack_link_announce(vi);
>> +}
>> +
>>   static int virtnet_close(struct net_device *dev)
>>   {
>>   	struct virtnet_info *vi = netdev_priv(dev);
>>
>>   	/* Make sure refill_work doesn't re-enable napi! */
>>   	cancel_delayed_work_sync(&vi->refill);
>> +	cancel_work_sync(&vi->announce);
> I think that a config change event can trigger after this point,
> so cancel here won't be effective. But why do it here?
> virtnet_remove not a better place? We can do it
> after remove_vq_common.

Sure.
>>   	napi_disable(&vi->napi);
>>
>>   	return 0;
>> @@ -962,11 +983,17 @@ static void virtnet_update_status(struct virtnet_info *vi)
>>   		return;
>>
>>   	/* Ignore unknown (future) status bits */
>> -	v&= VIRTIO_NET_S_LINK_UP;
>> +	v&= VIRTIO_NET_S_LINK_UP | VIRTIO_NET_S_ANNOUNCE;
> The announce bit in vi->status is always clear,
> so this is IMO confusing. I would do:
>
> 	if (v&  VIRTIO_NET_S_ANNOUNCE) {
> 		schedule
> 	}
>
> 	v&= VIRTIO_NET_S_LINK_UP;
>
> and the rest of the logic is not necessary then.
>
> Also, this might run extra ack announce commands after
> VIRTIO_NET_S_ANNOUNCE bit is clear. The spec
> isn't clear on whether this is legal.
>
> It would be very hard to fix this, so let's add a comment
> stating that it's legal, and clarify the spec
> in any case.

How about delay the clearing of VIRTIO_NET_S_ANNOUNCE bit in the 
workqueue and protect the updating with 
spinlock_irqsave()/spinloc_irqrestore()? Then later notification would 
be suppressed if the sending is not completed.
>>
>>   	if (vi->status == v)
>>   		return;
>>
>> +	if (v&  VIRTIO_NET_S_ANNOUNCE) {
>> +		v&= ~VIRTIO_NET_S_ANNOUNCE;
>> +		if (v&  VIRTIO_NET_S_LINK_UP)
>> +			schedule_work(&vi->announce);
> I think we really want an nrt wq here - if this triggers
> multiple times there's no good reason to try and run
> the ack command many times in parallel.

Yes.
>> +	}
>> +
>>   	vi->status = v;
>>
>>   	if (vi->status&  VIRTIO_NET_S_LINK_UP) {
>
>> @@ -1076,6 +1103,7 @@ static int virtnet_probe(struct virtio_device *vdev)
>>   		goto free;
>>
>>   	INIT_DELAYED_WORK(&vi->refill, refill_work);
>> +	INIT_WORK(&vi->announce, announce_work);
>>   	sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg));
>>   	sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg));
>>
>> @@ -1187,6 +1215,7 @@ static int virtnet_freeze(struct virtio_device *vdev)
>>   	virtqueue_disable_cb(vi->svq);
>>   	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
>>   		virtqueue_disable_cb(vi->cvq);
>> +	cancel_work_sync(&vi->announce);
> A config change event can trigger after this point,
> so cancel here won't be effective.
> Possibly, we need state like config_enable in the block
> device.

Probably needed.
>
> Also, what exactly will happen on suspend?
> As we reset, ANNOUCE bit will be clear so -
> do we forget to announce? Probably not good ...

This problem should be the same as normal suspending/resuming, if user 
want to announce the link they should use arp_notify instead.
>
>>
>>   	netif_device_detach(vi->dev);
>>   	cancel_delayed_work_sync(&vi->refill);
>> @@ -1233,6 +1262,7 @@ static unsigned int features[] = {
>>   	VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
>>   	VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
>>   	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
>> +	VIRTIO_NET_F_GUEST_ANNOUNCE,
>>   };
>>
>>   static struct virtio_driver virtio_net_driver = {
>> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
>> index 970d5a2..383e8a0 100644
>> --- a/include/linux/virtio_net.h
>> +++ b/include/linux/virtio_net.h
>> @@ -49,8 +49,10 @@
>>   #define VIRTIO_NET_F_CTRL_RX	18	/* Control channel RX mode support */
>>   #define VIRTIO_NET_F_CTRL_VLAN	19	/* Control channel VLAN filtering */
>>   #define VIRTIO_NET_F_CTRL_RX_EXTRA 20	/* Extra RX mode control support */
>> +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21  /* Guest can send gratituous packet */
> Rusty aligned the comments using tabs so let's do it here too?
> A better comment 'can announce device on the network'.
>
>>
>>   #define VIRTIO_NET_S_LINK_UP	1	/* Link is up */
>> +#define VIRTIO_NET_S_ANNOUNCE   2	/* Announcement is needed */
> why 3 spaces before the value here?
>
>>
>>   struct virtio_net_config {
>>   	/* The config defining mac address (if VIRTIO_NET_F_MAC) */
>> @@ -152,4 +154,15 @@ struct virtio_net_ctrl_mac {
>>    #define VIRTIO_NET_CTRL_VLAN_ADD             0
>>    #define VIRTIO_NET_CTRL_VLAN_DEL             1
>>
>> +/*
>> + * Control link announce acknowledgement
>> + *
>> + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that
>> + * driver has recevied the notification and device would clear the
> s/recevied/received/
>
> A bit clearer to replace 'and' with ; here.
>
>> + * VIRTIO_NET_S_ANNOUNCE bit in the status filed after it received
> s/filed/field/
> s/received/receives/
>
>> + * this command.
>> + */
>> +#define VIRTIO_NET_CTRL_ANNOUNCE       3
>> + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK         0
>> +
>>   #endif /* _LINUX_VIRTIO_NET_H */
>>
>> _______________________________________________
>> Virtualization mailing list
>> Virtualization@lists.linux-foundation.org
>> https://lists.linuxfoundation.org/mailman/listinfo/virtualization

  reply	other threads:[~2012-04-05  5:56 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-28  5:44 [V6 PATCH] virtio-net: send gratuitous packets when needed Jason Wang
2012-03-28  5:44 ` [Qemu-devel] " Jason Wang
2012-04-03 21:49 ` David Miller
2012-04-03 21:49   ` [Qemu-devel] " David Miller
2012-04-03 21:49   ` David Miller
2012-04-04  7:51   ` Michael S. Tsirkin
2012-04-04  7:51     ` [Qemu-devel] " Michael S. Tsirkin
2012-04-04  7:51     ` Michael S. Tsirkin
2012-04-04  7:49 ` Michael S. Tsirkin
2012-04-04  7:49   ` [Qemu-devel] " Michael S. Tsirkin
2012-04-04  7:49   ` Michael S. Tsirkin
2012-04-05  5:56   ` Jason Wang [this message]
2012-04-05  5:56     ` [Qemu-devel] " Jason Wang
2012-04-05  5:56     ` Jason Wang
2012-04-05  6:37     ` Michael S. Tsirkin
2012-04-05  6:37       ` [Qemu-devel] " Michael S. Tsirkin
2012-04-05  6:37       ` Michael S. Tsirkin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F7D33FF.2060304@redhat.com \
    --to=jasowang@redhat.com \
    --cc=amit.shah@redhat.com \
    --cc=davem@davemloft.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=qemu-devel@nongnu.org \
    --cc=virtualization@lists.linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.