virtio-net: Add promiscuous and all-multicast mode status bits
PATCH 3/5 virtio-net: Add promiscuous and all-multicast mode status bits
Set via control virtqueue. For compatibility with older guest drivers we need to default to promiscuous.
Signed-off-by Alex Williamson <[email protected]>
---
qemu/hw/virtio-net.c | 41 ++++++++++++++++++++++++++++++++++++++--- qemu/hw/virtio-net.h | 4 ++++ 2 files changed, 42 insertions(+), 3 deletions(-)
qemu/hw/virtio-net.c +38 -3
@@ -21,6 +21,8 @@#define TAP_VNET_HDR +#define VIRTIO_VM_VERSION 3 + typedef struct VirtIONet { VirtIODevice vdev;
@@ -32,6 +34,8 @@ typedef struct VirtIONetQEMUTimer *tx_timer;int tx_timer_active;int mergeable_rx_bufs; +int promisc; +int allmulti; } VirtIONet;/* TODO
@@ -113,6 +117,7 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)static void virtio_net_handle_ctrl (VirtIODevice *vdev,VirtQueue *vq) { +VirtIONet *n =to_virtio_net (vdev);struct {uint8_t class;uint8_t cmd;
@@ -134,7 +139,27 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) ctrl = (void *)elem.out_sg[0 ].iov_base; status = (void *)elem.in_sg[elem.in_num -1 ].iov_base; - *status =VIRTIO_NET_ERR ; + *status =VIRTIO_NET_OK ; + +if (ctrl->class ==VIRTIO_NET_CTRL_RX_MODE ) { +uint8_t *on; + +if (elem.out_num !=2 || elem.out_sg[1 ].iov_len !=sizeof (*on)) { +fprintf (stderr,"virtio-net ctrl invalid rx mode command\n" ); +exit (1 ); + } + + on = (void *)elem.out_sg[1 ].iov_base; + +if (ctrl->cmd ==VIRTIO_NET_CTRL_RX_MODE_PROMISC ) + n->promisc = *on; +else if (ctrl->cmd ==VIRTIO_NET_CTRL_RX_MODE_ALLMULTI ) + n->allmulti = *on; +else + *status =VIRTIO_NET_ERR ; + }else { + *status =VIRTIO_NET_ERR ; + }virtqueue_push (vq, &elem,sizeof (*status));virtio_notify (vdev, vq);
@@ -409,13 +434,15 @@ static void virtio_net_save(QEMUFile *f, void *opaque)#ifdef TAP_VNET_HDR qemu_put_be32 (f,tap_has_vnet_hdr (n->vc->vlan->first_client));#endif +qemu_put_be32 (f, n->promisc); +qemu_put_be32 (f, n->allmulti); }static int virtio_net_load (QEMUFile *f,void *opaque,int version_id) {VirtIONet *n = opaque; -if (version_id !=2 ) +if (version_id <2 || version_id >VIRTIO_VM_VERSION )return -EINVAL ;virtio_load (&n->vdev, f);
@@ -429,6 +456,13 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)tap_using_vnet_hdr (n->vc->vlan->first_client,1 );#endif +if (version_id >=3 ) { + n->promisc =qemu_get_be32 (f); + n->allmulti =qemu_get_be32 (f); + }else { + n->promisc =1 ; + } +if (n->tx_timer_active) {qemu_mod_timer (n->tx_timer,qemu_get_clock (vm_clock) +TX_TIMER_INTERVAL );
@@ -465,8 +499,9 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) n->tx_timer =qemu_new_timer (vm_clock, virtio_net_tx_timer, n); n->tx_timer_active =0 ; n->mergeable_rx_bufs =0 ; + n->promisc =1 ;/* for compatibility */ -register_savevm ("virtio-net" , virtio_net_id++,2 , +register_savevm ("virtio-net" , virtio_net_id++,VIRTIO_VM_VERSION , virtio_net_save, virtio_net_load, n);return (PCIDevice *)n;
qemu/hw/virtio-net.h +4 -0
@@ -80,4 +80,8 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);#define VIRTIO_NET_OK 0#define VIRTIO_NET_ERR 1 +#define VIRTIO_NET_CTRL_RX_MODE 0 +#define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0 +#define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI 1 +#endif