Message ID | 20090201200515.8183.81496.stgit@debian.lart |
---|---|
State | Changes Requested, archived |
Delegated to: | David Miller |
Headers | show |
On Monday 02 February 2009 06:35:15 Alex Williamson wrote: > + sg_set_buf(&sg, &promisc, sizeof(promisc)); > + > + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, > + VIRTIO_NET_CTRL_RX_PROMISC, > + &sg, 1, 0)) Hmm, can we use sg_init_one(&sg, &promisc, sizeof(promisc)) then pass two sg to virtnet_send_command? ie. change virtnet_send_command to: static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, struct scatterlist *out, struct scatterlist *in); NULL = no sg, otherwise it's assumed to be a nicely terminated sg? Neater for the callers I think... > -#define VIRTIO_NET_MAX_CTRL_ARGS 2 > +#define VIRTIO_NET_MAX_CTRL_ARGS 3 Oh, and this should probably be called VIRTNET_SEND_COMMAND_SG_MAX, and be this value minus 2 (ie. informative for the caller of virtnet_send_command). Thanks, Rusty. PS. Oh, this actual patch was fine: Acked-by: Rusty Russell <rusty@rustcorp.com.au> -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Rusty, On Mon, 2009-02-02 at 20:22 +1030, Rusty Russell wrote: > On Monday 02 February 2009 06:35:15 Alex Williamson wrote: > > + sg_set_buf(&sg, &promisc, sizeof(promisc)); > > + > > + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, > > + VIRTIO_NET_CTRL_RX_PROMISC, > > + &sg, 1, 0)) > > Hmm, can we use sg_init_one(&sg, &promisc, sizeof(promisc)) then pass two sg > to virtnet_send_command? ie. change virtnet_send_command to: > > static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, > struct scatterlist *out, struct scatterlist *in); > > NULL = no sg, otherwise it's assumed to be a nicely terminated sg? Neater for > the callers I think... I think the caller still ends up passing the counts of out and in entries here or else we have to walk the lists in send_command(). Doable, but doesn't seem to be common practice that I can find. We should also then clear the termination once we copy the sg[] into our own, but functions to do that don't seem to exist (need an sg_unmark_end()). I had avoided anything that would call sg_init_table() on the caller provided sg[] to avoid that problem, does it need to be addressed? > > -#define VIRTIO_NET_MAX_CTRL_ARGS 2 > > +#define VIRTIO_NET_MAX_CTRL_ARGS 3 > > Oh, and this should probably be called VIRTNET_SEND_COMMAND_SG_MAX, and be > this value minus 2 (ie. informative for the caller of virtnet_send_command). Yes, and yes to moving it to the c file, no need to expose it. Thanks, Alex
On Tuesday 03 February 2009 08:04:07 Alex Williamson wrote: > Hi Rusty, > > On Mon, 2009-02-02 at 20:22 +1030, Rusty Russell wrote: > > static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, > > struct scatterlist *out, struct scatterlist *in); ... > I think the caller still ends up passing the counts of out and in > entries here or else we have to walk the lists in send_command(). > Doable, but doesn't seem to be common practice that I can find. Yes, I've frequently expressed unhappiness with the API. I lost that debate and it doesn't seem fruitful to return to it. It's not speed-critical, so just iterate. I refuse to make *my* APIs suck. > We > should also then clear the termination once we copy the sg[] into our > own, but functions to do that don't seem to exist (need an > sg_unmark_end()). Ideally we would chain them, but the caller would have to allocate an extra sg element. Implement sg_unmark_end() in a separate patch; be sure to CC Jens. > I had avoided anything that would call > sg_init_table() on the caller provided sg[] to avoid that problem, does > it need to be addressed? I don't think so: those args should in fact be const struct scatterlist *. Thanks, Rusty. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index d84e176..f43b9d3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -672,6 +672,36 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data) return ethtool_op_set_tx_hw_csum(dev, data); } +static void virtnet_set_rx_mode(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + struct scatterlist sg; + u8 promisc, allmulti; + + /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ + if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) + return; + + promisc = ((dev->flags & IFF_PROMISC) != 0 || dev->uc_count > 0); + allmulti = ((dev->flags & IFF_ALLMULTI) != 0 || dev->mc_count > 0); + + sg_set_buf(&sg, &promisc, sizeof(promisc)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, + VIRTIO_NET_CTRL_RX_PROMISC, + &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", + promisc ? "en" : "dis"); + + sg_set_buf(&sg, &allmulti, sizeof(allmulti)); + + if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, + VIRTIO_NET_CTRL_RX_ALLMULTI, + &sg, 1, 0)) + dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", + allmulti ? "en" : "dis"); +} + static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, @@ -696,6 +726,7 @@ static const struct net_device_ops virtnet_netdev = { .ndo_start_xmit = start_xmit, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = virtnet_set_mac_address, + .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = virtnet_netpoll, @@ -914,6 +945,7 @@ static unsigned int features[] = { VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */ VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, + VIRTIO_NET_F_CTRL_RX, VIRTIO_F_NOTIFY_ON_EMPTY, }; diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index f28a72a..69569e1 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -23,6 +23,7 @@ #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ @@ -76,6 +77,16 @@ typedef __u8 virtio_net_ctrl_ack; #define VIRTIO_NET_OK 0 #define VIRTIO_NET_ERR 1 -#define VIRTIO_NET_MAX_CTRL_ARGS 2 +#define VIRTIO_NET_MAX_CTRL_ARGS 3 + +/* + * Control the RX mode, ie. promisucous and allmulti. PROMISC and + * ALLMULTI commands require an "out" sg entry containing a 1 byte + * state value, zero = disable, non-zero = enable. These commands + * are supported with the VIRTIO_NET_F_CTRL_RX feature. + */ +#define VIRTIO_NET_CTRL_RX 0 + #define VIRTIO_NET_CTRL_RX_PROMISC 0 + #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 #endif /* _LINUX_VIRTIO_NET_H */
Make use of the RX_MODE control virtqueue class to enable the set_rx_mode netdev interface. This allows us to selectively enable/disable promiscuous and allmulti mode so we don't see packets we don't want. For now, we automatically enable these as needed if additional unicast or multicast addresses are requested. Signed-off-by: Alex Williamson <alex.williamson@hp.com> --- drivers/net/virtio_net.c | 32 ++++++++++++++++++++++++++++++++ include/linux/virtio_net.h | 13 ++++++++++++- 2 files changed, 44 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html