From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52833) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHVxW-0001U8-B4 for qemu-devel@nongnu.org; Wed, 13 Aug 2014 06:39:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XHVxN-0001gT-7N for qemu-devel@nongnu.org; Wed, 13 Aug 2014 06:39:10 -0400 Received: from mail-pa0-x244.google.com ([2607:f8b0:400e:c03::244]:59382) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XHVxM-0001gA-SV for qemu-devel@nongnu.org; Wed, 13 Aug 2014 06:39:01 -0400 Received: by mail-pa0-f68.google.com with SMTP id eu11so6843212pac.3 for ; Wed, 13 Aug 2014 03:38:59 -0700 (PDT) Received: from ubuntu.ubuntu-domain ([202.114.6.108]) by mx.google.com with ESMTPSA id un15sm5599050pab.14.2014.08.13.03.38.57 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 13 Aug 2014 03:38:58 -0700 (PDT) From: Hengjinxiao Date: Wed, 13 Aug 2014 18:37:57 +0800 Message-Id: <1407926277-11881-1-git-send-email-hjxiaohust@gmail.com> Subject: [Qemu-devel] [PATCH 1/1] add loopback for virtio-net List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Sometimes it is necessary to test whether virtio-net can send and receive packets normally, just as e1000 does. This patch adds loopback for virtio-net, when the command 'VIRTIO_NET_CTRL_LOOPBACK_SET' is sent from front-end driver(such as virtio-net driver in linux.git), virtio-net goes into loopback mode, and the test above can be executed, then command 'VIRTIO_NET_CTRL_LOOPBACK_UNSET' can make virtio-net go back to previous state. Signed-off-by: Hengjinxiao --- hw/net/virtio-net.c | 26 +++++++++++++++++++++++--- include/hw/virtio/virtio-net.h | 9 +++++++++ include/hw/virtio/virtio.h | 1 + include/net/net.h | 1 + net/net.c | 7 +++++-- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 268eff9..ca313f4 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -778,6 +778,22 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, return VIRTIO_NET_OK; } + +static int virtio_net_handle_loopback(VirtIONet *n, uint8_t cmd, + struct iovec *iov, unsigned int iov_cnt) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(n); + if (cmd == VIRTIO_NET_CTRL_LOOPBACK_SET) { + vdev->loopback = 1; + return VIRTIO_NET_OK; + } else if (cmd == VIRTIO_NET_CTRL_LOOPBACK_UNSET) { + vdev->loopback = 0; + return VIRTIO_NET_OK; + } else { + return VIRTIO_NET_ERR; + } +} + static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) { VirtIONet *n = VIRTIO_NET(vdev); @@ -813,6 +829,8 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) status = virtio_net_handle_mq(n, ctrl.cmd, iov, iov_cnt); } else if (ctrl.class == VIRTIO_NET_CTRL_GUEST_OFFLOADS) { status = virtio_net_handle_offloads(n, ctrl.cmd, iov, iov_cnt); + } else if (ctrl.class == VIRTIO_NET_CTRL_LOOPBACK) { + status = virtio_net_handle_loopback(n, ctrl.cmd, iov, iov_cnt); } s = iov_from_buf(elem.in_sg, elem.in_num, 0, &status, sizeof(status)); @@ -1108,6 +1126,9 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) VirtQueueElement elem; int32_t num_packets = 0; int queue_index = vq2q(virtio_get_queue_index(q->tx_vq)); + NetClientState *sender = qemu_get_subqueue(n->nic, queue_index); + + sender->loopback = vdev->loopback; if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) { return num_packets; } @@ -1156,9 +1177,8 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q) } len = n->guest_hdr_len; - - ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index), - out_sg, out_num, virtio_net_tx_complete); + + ret = qemu_sendv_packet_async(sender, out_sg, out_num, + virtio_net_tx_complete); if (ret == 0) { virtio_queue_set_notification(q->tx_vq, 0); q->async_tx.elem = elem; diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h index 6ceb5aa..24e56bf 100644 --- a/include/hw/virtio/virtio-net.h +++ b/include/hw/virtio/virtio-net.h @@ -257,6 +257,15 @@ struct virtio_net_ctrl_mq { #define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 + /* + * Control Loopback + * + * The command VIRTIO_NET_CTRL_LOOPBACK_SET is used to require the device + * come into loopback state. + */ +#define VIRTIO_NET_CTRL_LOOPBACK 6 + #define VIRTIO_NET_CTRL_LOOPBACK_SET 0 + #define VIRTIO_NET_CTRL_LOOPBACK_UNSET 1 #define DEFINE_VIRTIO_NET_FEATURES(_state, _field) \ DEFINE_PROP_BIT("any_layout", _state, _field, VIRTIO_F_ANY_LAYOUT, true), \ DEFINE_PROP_BIT("csum", _state, _field, VIRTIO_NET_F_CSUM, true), \ diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index a60104c..219e0d2 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -128,6 +128,7 @@ struct VirtIODevice VMChangeStateEntry *vmstate; char *bus_name; uint8_t device_endian; + uint8_t loopback; }; typedef struct VirtioDeviceClass { diff --git a/include/net/net.h b/include/net/net.h index ed594f9..ce66b86 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -89,6 +89,7 @@ struct NetClientState { NetClientDestructor *destructor; unsigned int queue_index; unsigned rxfilter_notify_enabled:1; + int loopback; }; typedef struct NICState { diff --git a/net/net.c b/net/net.c index 6d930ea..f4c1ef4 100644 --- a/net/net.c +++ b/net/net.c @@ -611,8 +611,11 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender, if (sender->link_down || !sender->peer) { return iov_size(iov, iovcnt); } - - queue = sender->peer->incoming_queue; + if (sender->loopback) { + queue = sender->incoming_queue; + } else { + queue = sender->peer->incoming_queue; + } return qemu_net_queue_send_iov(queue, sender, QEMU_NET_PACKET_FLAG_NONE, -- 1.8.3.2