Commit 3d11d36c7fef499128c4194cea7c58d0f7af82ec

Authored by aliguori
1 parent 79674068

qemu:virtio-net: Add a virtqueue for control commands from the guest (Alex Williamson)

This will be used for RX mode, MAC table, VLAN table control, etc...

The control transaction consists of one or more "out" sg entries and
one or more "in" sg entries.  The first out entry contains a header
defining the class and command.  Additional out entries may provide
data for the command.  A response via the ack entry is required
and the guest will typically be waiting for it.

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@6536 c046a42c-6fe2-441c-8c8c-71466251a162
hw/virtio-net.c
@@ -25,6 +25,7 @@ typedef struct VirtIONet @@ -25,6 +25,7 @@ typedef struct VirtIONet
25 uint16_t status; 25 uint16_t status;
26 VirtQueue *rx_vq; 26 VirtQueue *rx_vq;
27 VirtQueue *tx_vq; 27 VirtQueue *tx_vq;
  28 + VirtQueue *ctrl_vq;
28 VLANClientState *vc; 29 VLANClientState *vc;
29 QEMUTimer *tx_timer; 30 QEMUTimer *tx_timer;
30 int tx_timer_active; 31 int tx_timer_active;
@@ -79,7 +80,9 @@ static void virtio_net_set_link_status(VLANClientState *vc) @@ -79,7 +80,9 @@ static void virtio_net_set_link_status(VLANClientState *vc)
79 80
80 static uint32_t virtio_net_get_features(VirtIODevice *vdev) 81 static uint32_t virtio_net_get_features(VirtIODevice *vdev)
81 { 82 {
82 - uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS); 83 + uint32_t features = (1 << VIRTIO_NET_F_MAC) |
  84 + (1 << VIRTIO_NET_F_STATUS) |
  85 + (1 << VIRTIO_NET_F_CTRL_VQ);
83 86
84 return features; 87 return features;
85 } 88 }
@@ -91,6 +94,34 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) @@ -91,6 +94,34 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
91 n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); 94 n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
92 } 95 }
93 96
  97 +static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
  98 +{
  99 + struct virtio_net_ctrl_hdr ctrl;
  100 + virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
  101 + VirtQueueElement elem;
  102 +
  103 + while (virtqueue_pop(vq, &elem)) {
  104 + if ((elem.in_num < 1) || (elem.out_num < 1)) {
  105 + fprintf(stderr, "virtio-net ctrl missing headers\n");
  106 + exit(1);
  107 + }
  108 +
  109 + if (elem.out_sg[0].iov_len < sizeof(ctrl) ||
  110 + elem.out_sg[elem.in_num - 1].iov_len < sizeof(status)) {
  111 + fprintf(stderr, "virtio-net ctrl header not in correct element\n");
  112 + exit(1);
  113 + }
  114 +
  115 + ctrl.class = ldub_p(elem.out_sg[0].iov_base);
  116 + ctrl.cmd = ldub_p(elem.out_sg[0].iov_base + sizeof(ctrl.class));
  117 +
  118 + stb_p(elem.in_sg[elem.in_num - 1].iov_base, status);
  119 +
  120 + virtqueue_push(vq, &elem, sizeof(status));
  121 + virtio_notify(vdev, vq);
  122 + }
  123 +}
  124 +
94 /* RX */ 125 /* RX */
95 126
96 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) 127 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
@@ -356,6 +387,7 @@ void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) @@ -356,6 +387,7 @@ void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
356 n->vdev.set_features = virtio_net_set_features; 387 n->vdev.set_features = virtio_net_set_features;
357 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); 388 n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
358 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); 389 n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx);
  390 + n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl);
359 memcpy(n->mac, nd->macaddr, ETH_ALEN); 391 memcpy(n->mac, nd->macaddr, ETH_ALEN);
360 n->status = VIRTIO_NET_S_LINK_UP; 392 n->status = VIRTIO_NET_S_LINK_UP;
361 n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, 393 n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name,
hw/virtio-net.h
@@ -40,6 +40,7 @@ @@ -40,6 +40,7 @@
40 #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ 40 #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
41 #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ 41 #define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
42 #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ 42 #define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */
  43 +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */
43 44
44 #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ 45 #define VIRTIO_NET_S_LINK_UP 1 /* Link is up */
45 46
@@ -84,4 +85,21 @@ struct virtio_net_hdr_mrg_rxbuf @@ -84,4 +85,21 @@ struct virtio_net_hdr_mrg_rxbuf
84 85
85 void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn); 86 void virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
86 87
  88 +/*
  89 + * Control virtqueue data structures
  90 + *
  91 + * The control virtqueue expects a header in the first sg entry
  92 + * and an ack/status response in the last entry. Data for the
  93 + * command goes in between.
  94 + */
  95 +struct virtio_net_ctrl_hdr {
  96 + uint8_t class;
  97 + uint8_t cmd;
  98 +};
  99 +
  100 +typedef uint8_t virtio_net_ctrl_ack;
  101 +
  102 +#define VIRTIO_NET_OK 0
  103 +#define VIRTIO_NET_ERR 1
  104 +
87 #endif 105 #endif