From patchwork Wed Feb 4 22:59:58 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Williamson X-Patchwork-Id: 5528 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n14MxUEG001447 for ; Wed, 4 Feb 2009 22:59:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755127AbZBDW7X (ORCPT ); Wed, 4 Feb 2009 17:59:23 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755081AbZBDW7X (ORCPT ); Wed, 4 Feb 2009 17:59:23 -0500 Received: from g1t0026.austin.hp.com ([15.216.28.33]:11906 "EHLO g1t0026.austin.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754883AbZBDW7W (ORCPT ); Wed, 4 Feb 2009 17:59:22 -0500 Received: from g4t0009.houston.hp.com (g4t0009.houston.hp.com [16.234.32.26]) by g1t0026.austin.hp.com (Postfix) with ESMTP id C4D1AC096; Wed, 4 Feb 2009 22:59:21 +0000 (UTC) Received: from ldl.fc.hp.com (ldl.fc.hp.com [15.11.146.30]) by g4t0009.houston.hp.com (Postfix) with ESMTP id 4CA23C0D9; Wed, 4 Feb 2009 22:59:21 +0000 (UTC) Received: from localhost (ldl.fc.hp.com [127.0.0.1]) by ldl.fc.hp.com (Postfix) with ESMTP id BC98639C06E; Wed, 4 Feb 2009 15:59:20 -0700 (MST) X-Virus-Scanned: Debian amavisd-new at ldl.fc.hp.com Received: from ldl.fc.hp.com ([127.0.0.1]) by localhost (ldl.fc.hp.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Qx7EP70Xh-UM; Wed, 4 Feb 2009 15:59:18 -0700 (MST) Received: from [10.91.73.10] (lart.fc.hp.com [15.11.146.31]) by ldl.fc.hp.com (Postfix) with ESMTP id C492339C00E; Wed, 4 Feb 2009 15:59:18 -0700 (MST) Subject: Re: [PATCH v2 4/8] qemu:virtio-net: Add a virtqueue for control commands from the guest From: Alex Williamson To: Anthony Liguori Cc: qemu-devel@nongnu.org, kvm@vger.kernel.org, markmc@redhat.com In-Reply-To: <4988AF7C.50103@codemonkey.ws> References: <20090203192932.19598.50925.stgit@kvm.aw> <20090203192953.19598.41310.stgit@kvm.aw> <4988AF7C.50103@codemonkey.ws> Organization: OSLO R&D Date: Wed, 04 Feb 2009 15:59:58 -0700 Message-Id: <1233788398.7026.1237.camel@lappy> Mime-Version: 1.0 X-Mailer: Evolution 2.24.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org On Tue, 2009-02-03 at 14:56 -0600, Anthony Liguori wrote: > Alex Williamson wrote: > > + ctrl = elem.out_sg[0].iov_base; > > + status = elem.in_sg[elem.in_num - 1].iov_base; > > > > This works only because we're dealing with uint8_ts but it's broken > elsewhere in virtio-net. iov_base is guest memory which means it may > have different endianness. We really should be using ldub_p() here. > > > + *status = VIRTIO_NET_ERR; > > > > And stb_p() here. Thanks Anthony. So before I patch bomb again, I think this turns into something like below. This makes the struct definitions less useful on the backend side, but I'm not sure we can do anything about that. I assume for u16s and u32s used in other parts of the interface, we'll define those as little endian, which means the guest side driver eventually needs a follow-up patch for big endian archs. Thanks, Alex qemu:virtio-net: Add a virtqueue for control commands from the guest 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 --- hw/virtio-net.c | 34 +++++++++++++++++++++++++++++++++- hw/virtio-net.h | 18 ++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" 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/hw/virtio-net.c b/hw/virtio-net.c index 073f23a..7971f95 100644 --- a/hw/virtio-net.c +++ b/hw/virtio-net.c @@ -25,6 +25,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; @@ -79,7 +80,9 @@ static void virtio_net_set_link_status(VLANClientState *vc) static uint32_t virtio_net_get_features(VirtIODevice *vdev) { - uint32_t features = (1 << VIRTIO_NET_F_MAC) | (1 << VIRTIO_NET_F_STATUS); + uint32_t features = (1 << VIRTIO_NET_F_MAC) | + (1 << VIRTIO_NET_F_STATUS) | + (1 << VIRTIO_NET_F_CTRL_VQ); return features; } @@ -91,6 +94,34 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features) n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF)); } +static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) +{ + struct virtio_net_ctrl_hdr ctrl; + virtio_net_ctrl_ack status = VIRTIO_NET_ERR; + 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.class = ldub_p(elem.out_sg[0].iov_base); + ctrl.cmd = ldub_p(elem.out_sg[0].iov_base + sizeof(ctrl.class)); + + stb_p(elem.in_sg[elem.in_num - 1].iov_base, status); + + virtqueue_push(vq, &elem, sizeof(status)); + virtio_notify(vdev, vq); + } +} + /* RX */ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq) @@ -356,6 +387,7 @@ void 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/hw/virtio-net.h b/hw/virtio-net.h index 9dce663..119e38d 100644 --- a/hw/virtio-net.h +++ b/hw/virtio-net.h @@ -40,6 +40,7 @@ #define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ #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_S_LINK_UP 1 /* Link is up */ @@ -84,4 +85,21 @@ struct virtio_net_hdr_mrg_rxbuf void 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