From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LNvz5-0003ML-9z for qemu-devel@nongnu.org; Fri, 16 Jan 2009 16:12:07 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LNvz3-0003Jx-Bo for qemu-devel@nongnu.org; Fri, 16 Jan 2009 16:12:06 -0500 Received: from [199.232.76.173] (port=40445 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LNvz2-0003J1-JW for qemu-devel@nongnu.org; Fri, 16 Jan 2009 16:12:04 -0500 Received: from g4t0014.houston.hp.com ([15.201.24.17]:45252) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1LNvz2-0005sA-5i for qemu-devel@nongnu.org; Fri, 16 Jan 2009 16:12:04 -0500 From: Alex Williamson Date: Fri, 16 Jan 2009 14:10:10 -0700 Message-ID: <20090116211010.16725.26723.stgit@kvm.aw> In-Reply-To: <20090116210954.16725.44321.stgit@kvm.aw> References: <20090116210954.16725.44321.stgit@kvm.aw> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [PATCH 3/7] qemu:virtio-net: Add a virtqueue for control commands from the guest Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: kvm@vger.kernel.org Cc: markmc@redhat.com, qemu-devel@nongnu.org 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 --- qemu/hw/virtio-net.c | 29 +++++++++++++++++++++++++++++ qemu/hw/virtio-net.h | 17 +++++++++++++++++ 2 files changed, 46 insertions(+), 0 deletions(-) diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c index 44827bc..3d8cba7 100644 --- a/qemu/hw/virtio-net.c +++ b/qemu/hw/virtio-net.c @@ -32,6 +32,7 @@ typedef struct VirtIONet uint16_t status; VirtQueue *rx_vq; VirtQueue *tx_vq; + VirtQueue *ctrl_vq; VLANClientState *vc; QEMUTimer *tx_timer; int tx_timer_active; @@ -130,6 +131,33 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) #endif } +static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) +{ + struct virtio_net_ctrl_hdr *ctrl; + virtio_net_ctrl_ack *status; + VirtQueueElement elem; + + while (virtqueue_pop(vq, &elem)) { + if ((elem.in_num < 1) | (elem.out_num < 1)) { + fprintf(stderr, "virtio-net ctrl missing headers\n"); + exit(1); + } + + if (elem.out_sg[0].iov_len < sizeof(*ctrl) || + elem.out_sg[elem.in_num - 1].iov_len < sizeof(*status)) { + fprintf(stderr, "virtio-net ctrl header not in correct element\n"); + exit(1); + } + + ctrl = elem.out_sg[0].iov_base; + status = elem.in_sg[elem.in_num - 1].iov_base; + *status = VIRTIO_NET_ERR; + + virtqueue_push(vq, &elem, sizeof(*status)); + virtio_notify(vdev, vq); + } +} + /* RX */ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) @@ -458,6 +486,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn) n->vdev.set_features = virtio_net_set_features; n->rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx); n->tx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_tx); + n->ctrl_vq = virtio_add_queue(&n->vdev, 16, virtio_net_handle_ctrl); memcpy(n->mac, nd->macaddr, ETH_ALEN); n->status = VIRTIO_NET_S_LINK_UP; n->vc = qemu_new_vlan_client(nd->vlan, nd->model, nd->name, diff --git a/qemu/hw/virtio-net.h b/qemu/hw/virtio-net.h index 9ac9e34..9a9641e 100644 --- a/qemu/hw/virtio-net.h +++ b/qemu/hw/virtio-net.h @@ -82,4 +82,21 @@ struct virtio_net_hdr_mrg_rxbuf PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn); +/* + * Control virtqueue data structures + * + * The control virtqueue expects a header in the first sg entry + * and an ack/status response in the last entry. Data for the + * command goes in between. + */ +struct virtio_net_ctrl_hdr { + uint8_t class; + uint8_t cmd; +}; + +typedef uint8_t virtio_net_ctrl_ack; + +#define VIRTIO_NET_OK 0 +#define VIRTIO_NET_ERR 1 + #endif