Commit 002437cd42a84261fed26b2d0c3feae0e0c9b241

Authored by aliguori
1 parent 3d11d36c

qemu:virtio-net: Add promiscuous and all-multicast mode bits (Alex Williamson)

Add a new RX_MODE control virtqueue class with commands PROMISC and
ALLMULTI and usage documented in virtio-net.h allowing the guest to
manipulate packet receiving options.  We don't export a feature for
this until we also add the MAC filter table.

Note, for compatibility with older guest drivers we need to default
to promiscuous.

Signed-off-by: Alex Williamson <alex.williamson@hp.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6537 c046a42c-6fe2-441c-8c8c-71466251a162
hw/virtio-net.c
... ... @@ -16,7 +16,7 @@
16 16 #include "qemu-timer.h"
17 17 #include "virtio-net.h"
18 18  
19   -#define VIRTIO_NET_VM_VERSION 3
  19 +#define VIRTIO_NET_VM_VERSION 4
20 20  
21 21 typedef struct VirtIONet
22 22 {
... ... @@ -30,6 +30,8 @@ typedef struct VirtIONet
30 30 QEMUTimer *tx_timer;
31 31 int tx_timer_active;
32 32 int mergeable_rx_bufs;
  33 + int promisc;
  34 + int allmulti;
33 35 } VirtIONet;
34 36  
35 37 /* TODO
... ... @@ -78,6 +80,15 @@ static void virtio_net_set_link_status(VLANClientState *vc)
78 80 virtio_notify_config(&n->vdev);
79 81 }
80 82  
  83 +static void virtio_net_reset(VirtIODevice *vdev)
  84 +{
  85 + VirtIONet *n = to_virtio_net(vdev);
  86 +
  87 + /* Reset back to compatibility mode */
  88 + n->promisc = 1;
  89 + n->allmulti = 0;
  90 +}
  91 +
81 92 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
82 93 {
83 94 uint32_t features = (1 << VIRTIO_NET_F_MAC) |
... ... @@ -94,8 +105,31 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
94 105 n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
95 106 }
96 107  
  108 +static int virtio_net_handle_rx_mode(VirtIONet *n, uint8_t cmd,
  109 + VirtQueueElement *elem)
  110 +{
  111 + uint8_t on;
  112 +
  113 + if (elem->out_num != 2 || elem->out_sg[1].iov_len != sizeof(on)) {
  114 + fprintf(stderr, "virtio-net ctrl invalid rx mode command\n");
  115 + exit(1);
  116 + }
  117 +
  118 + on = ldub_p(elem->out_sg[1].iov_base);
  119 +
  120 + if (cmd == VIRTIO_NET_CTRL_RX_MODE_PROMISC)
  121 + n->promisc = on;
  122 + else if (cmd == VIRTIO_NET_CTRL_RX_MODE_ALLMULTI)
  123 + n->allmulti = on;
  124 + else
  125 + return VIRTIO_NET_ERR;
  126 +
  127 + return VIRTIO_NET_OK;
  128 +}
  129 +
97 130 static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
98 131 {
  132 + VirtIONet *n = to_virtio_net(vdev);
99 133 struct virtio_net_ctrl_hdr ctrl;
100 134 virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
101 135 VirtQueueElement elem;
... ... @@ -115,6 +149,9 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
115 149 ctrl.class = ldub_p(elem.out_sg[0].iov_base);
116 150 ctrl.cmd = ldub_p(elem.out_sg[0].iov_base + sizeof(ctrl.class));
117 151  
  152 + if (ctrl.class == VIRTIO_NET_CTRL_RX_MODE)
  153 + status = virtio_net_handle_rx_mode(n, ctrl.cmd, &elem);
  154 +
118 155 stb_p(elem.in_sg[elem.in_num - 1].iov_base, status);
119 156  
120 157 virtqueue_push(vq, &elem, sizeof(status));
... ... @@ -339,6 +376,8 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
339 376 qemu_put_be32(f, n->tx_timer_active);
340 377 qemu_put_be32(f, n->mergeable_rx_bufs);
341 378 qemu_put_be16(f, n->status);
  379 + qemu_put_be32(f, n->promisc);
  380 + qemu_put_be32(f, n->allmulti);
342 381 }
343 382  
344 383 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
... ... @@ -357,6 +396,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
357 396 if (version_id >= 3)
358 397 n->status = qemu_get_be16(f);
359 398  
  399 + if (version_id >= 4) {
  400 + n->promisc = qemu_get_be32(f);
  401 + n->allmulti = qemu_get_be32(f);
  402 + }
  403 +
360 404 if (n->tx_timer_active) {
361 405 qemu_mod_timer(n->tx_timer,
362 406 qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
... ... @@ -385,6 +429,7 @@ void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
385 429 n->vdev.set_config = virtio_net_set_config;
386 430 n->vdev.get_features = virtio_net_get_features;
387 431 n->vdev.set_features = virtio_net_set_features;
  432 + n->vdev.reset = virtio_net_reset;
388 433 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
389 434 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
390 435 n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl);
... ... @@ -399,6 +444,7 @@ void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
399 444 n->tx_timer = qemu_new_timer(vm_clock, virtio_net_tx_timer, n);
400 445 n->tx_timer_active = 0;
401 446 n->mergeable_rx_bufs = 0;
  447 + n->promisc = 1; /* for compatibility */
402 448  
403 449 register_savevm("virtio-net", virtio_net_id++, VIRTIO_NET_VM_VERSION,
404 450 virtio_net_save, virtio_net_load, n);
... ...
hw/virtio-net.h
... ... @@ -41,6 +41,7 @@
41 41 #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
42 42 #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
43 43 #define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */
  44 +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */
44 45  
45 46 #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
46 47  
... ... @@ -102,4 +103,14 @@ typedef uint8_t virtio_net_ctrl_ack;
102 103 #define VIRTIO_NET_OK 0
103 104 #define VIRTIO_NET_ERR 1
104 105  
  106 +/*
  107 + * Control the RX mode, ie. promisucous and allmulti. PROMISC and
  108 + * ALLMULTI commands require an "out" sg entry containing a 1 byte
  109 + * state value, zero = disable, non-zero = enable. These commands
  110 + * are supported with the VIRTIO_NET_F_CTRL_RX feature.
  111 + */
  112 +#define VIRTIO_NET_CTRL_RX_MODE 0
  113 + #define VIRTIO_NET_CTRL_RX_MODE_PROMISC 0
  114 + #define VIRTIO_NET_CTRL_RX_MODE_ALLMULTI 1
  115 +
105 116 #endif
... ...