get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/123286/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 123286,
    "url": "https://patches.dpdk.org/api/patches/123286/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/20230207151747.245808-2-maxime.coquelin@redhat.com/",
    "project": {
        "id": 1,
        "url": "https://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230207151747.245808-2-maxime.coquelin@redhat.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230207151747.245808-2-maxime.coquelin@redhat.com",
    "date": "2023-02-07T15:17:27",
    "name": "[v2,01/21] net/virtio: move CVQ code into a dedicated file",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "1eef900d376e1bd458dfb557aa0ce94aa9109792",
    "submitter": {
        "id": 512,
        "url": "https://patches.dpdk.org/api/people/512/?format=api",
        "name": "Maxime Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "delegate": {
        "id": 2642,
        "url": "https://patches.dpdk.org/api/users/2642/?format=api",
        "username": "mcoquelin",
        "first_name": "Maxime",
        "last_name": "Coquelin",
        "email": "maxime.coquelin@redhat.com"
    },
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/20230207151747.245808-2-maxime.coquelin@redhat.com/mbox/",
    "series": [
        {
            "id": 26854,
            "url": "https://patches.dpdk.org/api/series/26854/?format=api",
            "web_url": "https://patches.dpdk.org/project/dpdk/list/?series=26854",
            "date": "2023-02-07T15:17:33",
            "name": "Add control queue & MQ support to Virtio-user vDPA",
            "version": 2,
            "mbox": "https://patches.dpdk.org/series/26854/mbox/"
        }
    ],
    "comments": "https://patches.dpdk.org/api/patches/123286/comments/",
    "check": "success",
    "checks": "https://patches.dpdk.org/api/patches/123286/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id 7A95A41C30;\n\tTue,  7 Feb 2023 16:19:49 +0100 (CET)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 8AD7042DA0;\n\tTue,  7 Feb 2023 16:18:52 +0100 (CET)",
            "from us-smtp-delivery-124.mimecast.com\n (us-smtp-delivery-124.mimecast.com [170.10.129.124])\n by mails.dpdk.org (Postfix) with ESMTP id D910742D51\n for <dev@dpdk.org>; Tue,  7 Feb 2023 16:18:45 +0100 (CET)",
            "from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com\n [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-595-rF8A0OudMWikk4R5m34Lkg-1; Tue, 07 Feb 2023 10:18:44 -0500",
            "from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com\n [10.11.54.7])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx02.redhat.com (Postfix) with ESMTPS id A92973C106AB;\n Tue,  7 Feb 2023 15:17:55 +0000 (UTC)",
            "from max-t490s.redhat.com (unknown [10.39.208.26])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 32D77140EBF4;\n Tue,  7 Feb 2023 15:17:54 +0000 (UTC)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1675783125;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=bGSj4jxR6zmC7yRXjy3GtuFn6jAWo64tGSeueFnCw14=;\n b=KD+wOPbi6JWnlMhcUukVTwQd67IzdLJoIG5LXSCw/UGoiY0MXIHW8VQMZ1ZmtuhgRV1+i3\n lwsumRQuydO9JY9CabJr7Cyu4UZOLlME8HK4G4+3dneZtG4m81VX+XOm8hLRLjEzJqLQmZ\n +t8r4HfF8f6qeIdXWIXOXbqJxldYEW4=",
        "X-MC-Unique": "rF8A0OudMWikk4R5m34Lkg-1",
        "From": "Maxime Coquelin <maxime.coquelin@redhat.com>",
        "To": "dev@dpdk.org, chenbo.xia@intel.com, david.marchand@redhat.com,\n eperezma@redhat.com, stephen@networkplumber.org",
        "Cc": "Maxime Coquelin <maxime.coquelin@redhat.com>",
        "Subject": "[PATCH v2 01/21] net/virtio: move CVQ code into a dedicated file",
        "Date": "Tue,  7 Feb 2023 16:17:27 +0100",
        "Message-Id": "<20230207151747.245808-2-maxime.coquelin@redhat.com>",
        "In-Reply-To": "<20230207151747.245808-1-maxime.coquelin@redhat.com>",
        "References": "<20230207151747.245808-1-maxime.coquelin@redhat.com>",
        "MIME-Version": "1.0",
        "X-Scanned-By": "MIMEDefang 3.1 on 10.11.54.7",
        "X-Mimecast-Spam-Score": "0",
        "X-Mimecast-Originator": "redhat.com",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain; charset=\"US-ASCII\"; x-default=true",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "This patch moves Virtio control queue code into a dedicated\nfile, as preliminary rework to support shadow control queue\nin Virtio-user.\n\nSigned-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>\nReviewed-by: Chenbo Xia <chenbo.xia@intel.com>\n---\n drivers/net/virtio/meson.build     |   1 +\n drivers/net/virtio/virtio_cvq.c    | 230 +++++++++++++++++++++++++++++\n drivers/net/virtio/virtio_cvq.h    | 126 ++++++++++++++++\n drivers/net/virtio/virtio_ethdev.c | 218 +--------------------------\n drivers/net/virtio/virtio_rxtx.h   |   9 --\n drivers/net/virtio/virtqueue.h     | 105 +------------\n 6 files changed, 359 insertions(+), 330 deletions(-)\n create mode 100644 drivers/net/virtio/virtio_cvq.c\n create mode 100644 drivers/net/virtio/virtio_cvq.h",
    "diff": "diff --git a/drivers/net/virtio/meson.build b/drivers/net/virtio/meson.build\nindex d78b8278c6..0ffd77024e 100644\n--- a/drivers/net/virtio/meson.build\n+++ b/drivers/net/virtio/meson.build\n@@ -9,6 +9,7 @@ endif\n \n sources += files(\n         'virtio.c',\n+        'virtio_cvq.c',\n         'virtio_ethdev.c',\n         'virtio_pci_ethdev.c',\n         'virtio_pci.c',\ndiff --git a/drivers/net/virtio/virtio_cvq.c b/drivers/net/virtio/virtio_cvq.c\nnew file mode 100644\nindex 0000000000..de4299a2a7\n--- /dev/null\n+++ b/drivers/net/virtio/virtio_cvq.c\n@@ -0,0 +1,230 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2016 Intel Corporation\n+ * Copyright(c) 2022 Red Hat Inc,\n+ */\n+\n+#include <unistd.h>\n+\n+#include <rte_common.h>\n+#include <rte_eal.h>\n+#include <rte_errno.h>\n+\n+#include \"virtio_cvq.h\"\n+#include \"virtqueue.h\"\n+\n+static struct virtio_pmd_ctrl *\n+virtio_send_command_packed(struct virtnet_ctl *cvq,\n+\t\t\t   struct virtio_pmd_ctrl *ctrl,\n+\t\t\t   int *dlen, int pkt_num)\n+{\n+\tstruct virtqueue *vq = virtnet_cq_to_vq(cvq);\n+\tint head;\n+\tstruct vring_packed_desc *desc = vq->vq_packed.ring.desc;\n+\tstruct virtio_pmd_ctrl *result;\n+\tuint16_t flags;\n+\tint sum = 0;\n+\tint nb_descs = 0;\n+\tint k;\n+\n+\t/*\n+\t * Format is enforced in qemu code:\n+\t * One TX packet for header;\n+\t * At least one TX packet per argument;\n+\t * One RX packet for ACK.\n+\t */\n+\thead = vq->vq_avail_idx;\n+\tflags = vq->vq_packed.cached_flags;\n+\tdesc[head].addr = cvq->virtio_net_hdr_mem;\n+\tdesc[head].len = sizeof(struct virtio_net_ctrl_hdr);\n+\tvq->vq_free_cnt--;\n+\tnb_descs++;\n+\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n+\t\tvq->vq_avail_idx -= vq->vq_nentries;\n+\t\tvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;\n+\t}\n+\n+\tfor (k = 0; k < pkt_num; k++) {\n+\t\tdesc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem\n+\t\t\t+ sizeof(struct virtio_net_ctrl_hdr)\n+\t\t\t+ sizeof(ctrl->status) + sizeof(uint8_t) * sum;\n+\t\tdesc[vq->vq_avail_idx].len = dlen[k];\n+\t\tdesc[vq->vq_avail_idx].flags = VRING_DESC_F_NEXT |\n+\t\t\tvq->vq_packed.cached_flags;\n+\t\tsum += dlen[k];\n+\t\tvq->vq_free_cnt--;\n+\t\tnb_descs++;\n+\t\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n+\t\t\tvq->vq_avail_idx -= vq->vq_nentries;\n+\t\t\tvq->vq_packed.cached_flags ^=\n+\t\t\t\tVRING_PACKED_DESC_F_AVAIL_USED;\n+\t\t}\n+\t}\n+\n+\tdesc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem\n+\t\t+ sizeof(struct virtio_net_ctrl_hdr);\n+\tdesc[vq->vq_avail_idx].len = sizeof(ctrl->status);\n+\tdesc[vq->vq_avail_idx].flags = VRING_DESC_F_WRITE |\n+\t\tvq->vq_packed.cached_flags;\n+\tvq->vq_free_cnt--;\n+\tnb_descs++;\n+\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n+\t\tvq->vq_avail_idx -= vq->vq_nentries;\n+\t\tvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;\n+\t}\n+\n+\tvirtqueue_store_flags_packed(&desc[head], VRING_DESC_F_NEXT | flags,\n+\t\t\tvq->hw->weak_barriers);\n+\n+\tvirtio_wmb(vq->hw->weak_barriers);\n+\tvirtqueue_notify(vq);\n+\n+\t/* wait for used desc in virtqueue\n+\t * desc_is_used has a load-acquire or rte_io_rmb inside\n+\t */\n+\twhile (!desc_is_used(&desc[head], vq))\n+\t\tusleep(100);\n+\n+\t/* now get used descriptors */\n+\tvq->vq_free_cnt += nb_descs;\n+\tvq->vq_used_cons_idx += nb_descs;\n+\tif (vq->vq_used_cons_idx >= vq->vq_nentries) {\n+\t\tvq->vq_used_cons_idx -= vq->vq_nentries;\n+\t\tvq->vq_packed.used_wrap_counter ^= 1;\n+\t}\n+\n+\tPMD_INIT_LOG(DEBUG, \"vq->vq_free_cnt=%d\\n\"\n+\t\t\t\"vq->vq_avail_idx=%d\\n\"\n+\t\t\t\"vq->vq_used_cons_idx=%d\\n\"\n+\t\t\t\"vq->vq_packed.cached_flags=0x%x\\n\"\n+\t\t\t\"vq->vq_packed.used_wrap_counter=%d\",\n+\t\t\tvq->vq_free_cnt,\n+\t\t\tvq->vq_avail_idx,\n+\t\t\tvq->vq_used_cons_idx,\n+\t\t\tvq->vq_packed.cached_flags,\n+\t\t\tvq->vq_packed.used_wrap_counter);\n+\n+\tresult = cvq->virtio_net_hdr_mz->addr;\n+\treturn result;\n+}\n+\n+static struct virtio_pmd_ctrl *\n+virtio_send_command_split(struct virtnet_ctl *cvq,\n+\t\t\t  struct virtio_pmd_ctrl *ctrl,\n+\t\t\t  int *dlen, int pkt_num)\n+{\n+\tstruct virtio_pmd_ctrl *result;\n+\tstruct virtqueue *vq = virtnet_cq_to_vq(cvq);\n+\tuint32_t head, i;\n+\tint k, sum = 0;\n+\n+\thead = vq->vq_desc_head_idx;\n+\n+\t/*\n+\t * Format is enforced in qemu code:\n+\t * One TX packet for header;\n+\t * At least one TX packet per argument;\n+\t * One RX packet for ACK.\n+\t */\n+\tvq->vq_split.ring.desc[head].flags = VRING_DESC_F_NEXT;\n+\tvq->vq_split.ring.desc[head].addr = cvq->virtio_net_hdr_mem;\n+\tvq->vq_split.ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr);\n+\tvq->vq_free_cnt--;\n+\ti = vq->vq_split.ring.desc[head].next;\n+\n+\tfor (k = 0; k < pkt_num; k++) {\n+\t\tvq->vq_split.ring.desc[i].flags = VRING_DESC_F_NEXT;\n+\t\tvq->vq_split.ring.desc[i].addr = cvq->virtio_net_hdr_mem\n+\t\t\t+ sizeof(struct virtio_net_ctrl_hdr)\n+\t\t\t+ sizeof(ctrl->status) + sizeof(uint8_t) * sum;\n+\t\tvq->vq_split.ring.desc[i].len = dlen[k];\n+\t\tsum += dlen[k];\n+\t\tvq->vq_free_cnt--;\n+\t\ti = vq->vq_split.ring.desc[i].next;\n+\t}\n+\n+\tvq->vq_split.ring.desc[i].flags = VRING_DESC_F_WRITE;\n+\tvq->vq_split.ring.desc[i].addr = cvq->virtio_net_hdr_mem\n+\t\t\t+ sizeof(struct virtio_net_ctrl_hdr);\n+\tvq->vq_split.ring.desc[i].len = sizeof(ctrl->status);\n+\tvq->vq_free_cnt--;\n+\n+\tvq->vq_desc_head_idx = vq->vq_split.ring.desc[i].next;\n+\n+\tvq_update_avail_ring(vq, head);\n+\tvq_update_avail_idx(vq);\n+\n+\tPMD_INIT_LOG(DEBUG, \"vq->vq_queue_index = %d\", vq->vq_queue_index);\n+\n+\tvirtqueue_notify(vq);\n+\n+\twhile (virtqueue_nused(vq) == 0)\n+\t\tusleep(100);\n+\n+\twhile (virtqueue_nused(vq)) {\n+\t\tuint32_t idx, desc_idx, used_idx;\n+\t\tstruct vring_used_elem *uep;\n+\n+\t\tused_idx = (uint32_t)(vq->vq_used_cons_idx\n+\t\t\t\t& (vq->vq_nentries - 1));\n+\t\tuep = &vq->vq_split.ring.used->ring[used_idx];\n+\t\tidx = (uint32_t)uep->id;\n+\t\tdesc_idx = idx;\n+\n+\t\twhile (vq->vq_split.ring.desc[desc_idx].flags &\n+\t\t\t\tVRING_DESC_F_NEXT) {\n+\t\t\tdesc_idx = vq->vq_split.ring.desc[desc_idx].next;\n+\t\t\tvq->vq_free_cnt++;\n+\t\t}\n+\n+\t\tvq->vq_split.ring.desc[desc_idx].next = vq->vq_desc_head_idx;\n+\t\tvq->vq_desc_head_idx = idx;\n+\n+\t\tvq->vq_used_cons_idx++;\n+\t\tvq->vq_free_cnt++;\n+\t}\n+\n+\tPMD_INIT_LOG(DEBUG, \"vq->vq_free_cnt=%d\\nvq->vq_desc_head_idx=%d\",\n+\t\t\tvq->vq_free_cnt, vq->vq_desc_head_idx);\n+\n+\tresult = cvq->virtio_net_hdr_mz->addr;\n+\treturn result;\n+}\n+\n+int\n+virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, int *dlen, int pkt_num)\n+{\n+\tvirtio_net_ctrl_ack status = ~0;\n+\tstruct virtio_pmd_ctrl *result;\n+\tstruct virtqueue *vq;\n+\n+\tctrl->status = status;\n+\n+\tif (!cvq) {\n+\t\tPMD_INIT_LOG(ERR, \"Control queue is not supported.\");\n+\t\treturn -1;\n+\t}\n+\n+\trte_spinlock_lock(&cvq->lock);\n+\tvq = virtnet_cq_to_vq(cvq);\n+\n+\tPMD_INIT_LOG(DEBUG, \"vq->vq_desc_head_idx = %d, status = %d, \"\n+\t\t\"vq->hw->cvq = %p vq = %p\",\n+\t\tvq->vq_desc_head_idx, status, vq->hw->cvq, vq);\n+\n+\tif (vq->vq_free_cnt < pkt_num + 2 || pkt_num < 1) {\n+\t\trte_spinlock_unlock(&cvq->lock);\n+\t\treturn -1;\n+\t}\n+\n+\tmemcpy(cvq->virtio_net_hdr_mz->addr, ctrl,\n+\t\tsizeof(struct virtio_pmd_ctrl));\n+\n+\tif (virtio_with_packed_queue(vq->hw))\n+\t\tresult = virtio_send_command_packed(cvq, ctrl, dlen, pkt_num);\n+\telse\n+\t\tresult = virtio_send_command_split(cvq, ctrl, dlen, pkt_num);\n+\n+\trte_spinlock_unlock(&cvq->lock);\n+\treturn result->status;\n+}\n+\ndiff --git a/drivers/net/virtio/virtio_cvq.h b/drivers/net/virtio/virtio_cvq.h\nnew file mode 100644\nindex 0000000000..139e813ffb\n--- /dev/null\n+++ b/drivers/net/virtio/virtio_cvq.h\n@@ -0,0 +1,126 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright(c) 2010-2015 Intel Corporation\n+ */\n+\n+#ifndef _VIRTIO_CVQ_H_\n+#define _VIRTIO_CVQ_H_\n+\n+#include <rte_ether.h>\n+\n+/**\n+ * Control the RX mode, ie. promiscuous, allmulti, etc...\n+ * All commands require an \"out\" sg entry containing a 1 byte\n+ * state value, zero = disable, non-zero = enable.  Commands\n+ * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.\n+ * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.\n+ */\n+#define VIRTIO_NET_CTRL_RX              0\n+#define VIRTIO_NET_CTRL_RX_PROMISC      0\n+#define VIRTIO_NET_CTRL_RX_ALLMULTI     1\n+#define VIRTIO_NET_CTRL_RX_ALLUNI       2\n+#define VIRTIO_NET_CTRL_RX_NOMULTI      3\n+#define VIRTIO_NET_CTRL_RX_NOUNI        4\n+#define VIRTIO_NET_CTRL_RX_NOBCAST      5\n+\n+/**\n+ * Control the MAC\n+ *\n+ * The MAC filter table is managed by the hypervisor, the guest should\n+ * assume the size is infinite.  Filtering should be considered\n+ * non-perfect, ie. based on hypervisor resources, the guest may\n+ * received packets from sources not specified in the filter list.\n+ *\n+ * In addition to the class/cmd header, the TABLE_SET command requires\n+ * two out scatterlists.  Each contains a 4 byte count of entries followed\n+ * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The\n+ * first sg list contains unicast addresses, the second is for multicast.\n+ * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature\n+ * is available.\n+ *\n+ * The ADDR_SET command requests one out scatterlist, it contains a\n+ * 6 bytes MAC address. This functionality is present if the\n+ * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.\n+ */\n+struct virtio_net_ctrl_mac {\n+\tuint32_t entries;\n+\tuint8_t macs[][RTE_ETHER_ADDR_LEN];\n+} __rte_packed;\n+\n+#define VIRTIO_NET_CTRL_MAC    1\n+#define VIRTIO_NET_CTRL_MAC_TABLE_SET        0\n+#define VIRTIO_NET_CTRL_MAC_ADDR_SET         1\n+\n+/**\n+ * Control VLAN filtering\n+ *\n+ * The VLAN filter table is controlled via a simple ADD/DEL interface.\n+ * VLAN IDs not added may be filtered by the hypervisor.  Del is the\n+ * opposite of add.  Both commands expect an out entry containing a 2\n+ * byte VLAN ID.  VLAN filtering is available with the\n+ * VIRTIO_NET_F_CTRL_VLAN feature bit.\n+ */\n+#define VIRTIO_NET_CTRL_VLAN     2\n+#define VIRTIO_NET_CTRL_VLAN_ADD 0\n+#define VIRTIO_NET_CTRL_VLAN_DEL 1\n+\n+/**\n+ * RSS control\n+ *\n+ * The RSS feature configuration message is sent by the driver when\n+ * VIRTIO_NET_F_RSS has been negotiated. It provides the device with\n+ * hash types to use, hash key and indirection table. In this\n+ * implementation, the driver only supports fixed key length (40B)\n+ * and indirection table size (128 entries).\n+ */\n+#define VIRTIO_NET_RSS_RETA_SIZE 128\n+#define VIRTIO_NET_RSS_KEY_SIZE 40\n+\n+struct virtio_net_ctrl_rss {\n+\tuint32_t hash_types;\n+\tuint16_t indirection_table_mask;\n+\tuint16_t unclassified_queue;\n+\tuint16_t indirection_table[VIRTIO_NET_RSS_RETA_SIZE];\n+\tuint16_t max_tx_vq;\n+\tuint8_t hash_key_length;\n+\tuint8_t hash_key_data[VIRTIO_NET_RSS_KEY_SIZE];\n+};\n+\n+/*\n+ * Control link announce acknowledgment\n+ *\n+ * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that\n+ * driver has received the notification; device would clear the\n+ * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives\n+ * this command.\n+ */\n+#define VIRTIO_NET_CTRL_ANNOUNCE     3\n+#define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0\n+\n+struct virtio_net_ctrl_hdr {\n+\tuint8_t class;\n+\tuint8_t cmd;\n+} __rte_packed;\n+\n+typedef uint8_t virtio_net_ctrl_ack;\n+\n+struct virtnet_ctl {\n+\t/**< memzone to populate hdr. */\n+\tconst struct rte_memzone *virtio_net_hdr_mz;\n+\trte_iova_t virtio_net_hdr_mem;  /**< hdr for each xmit packet */\n+\tuint16_t port_id;               /**< Device port identifier. */\n+\tconst struct rte_memzone *mz;   /**< mem zone to populate CTL ring. */\n+\trte_spinlock_t lock;              /**< spinlock for control queue. */\n+};\n+\n+#define VIRTIO_MAX_CTRL_DATA 2048\n+\n+struct virtio_pmd_ctrl {\n+\tstruct virtio_net_ctrl_hdr hdr;\n+\tvirtio_net_ctrl_ack status;\n+\tuint8_t data[VIRTIO_MAX_CTRL_DATA];\n+};\n+\n+int\n+virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl, int *dlen, int pkt_num);\n+\n+#endif /* _VIRTIO_RXTX_H_ */\ndiff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c\nindex 0ad740b253..d3aa420c89 100644\n--- a/drivers/net/virtio/virtio_ethdev.c\n+++ b/drivers/net/virtio/virtio_ethdev.c\n@@ -33,6 +33,7 @@\n #include \"virtio.h\"\n #include \"virtio_logs.h\"\n #include \"virtqueue.h\"\n+#include \"virtio_cvq.h\"\n #include \"virtio_rxtx.h\"\n #include \"virtio_rxtx_simple.h\"\n #include \"virtio_user/virtio_user_dev.h\"\n@@ -142,223 +143,6 @@ static const struct rte_virtio_xstats_name_off rte_virtio_txq_stat_strings[] = {\n \n struct virtio_hw_internal virtio_hw_internal[RTE_MAX_ETHPORTS];\n \n-static struct virtio_pmd_ctrl *\n-virtio_send_command_packed(struct virtnet_ctl *cvq,\n-\t\t\t   struct virtio_pmd_ctrl *ctrl,\n-\t\t\t   int *dlen, int pkt_num)\n-{\n-\tstruct virtqueue *vq = virtnet_cq_to_vq(cvq);\n-\tint head;\n-\tstruct vring_packed_desc *desc = vq->vq_packed.ring.desc;\n-\tstruct virtio_pmd_ctrl *result;\n-\tuint16_t flags;\n-\tint sum = 0;\n-\tint nb_descs = 0;\n-\tint k;\n-\n-\t/*\n-\t * Format is enforced in qemu code:\n-\t * One TX packet for header;\n-\t * At least one TX packet per argument;\n-\t * One RX packet for ACK.\n-\t */\n-\thead = vq->vq_avail_idx;\n-\tflags = vq->vq_packed.cached_flags;\n-\tdesc[head].addr = cvq->virtio_net_hdr_mem;\n-\tdesc[head].len = sizeof(struct virtio_net_ctrl_hdr);\n-\tvq->vq_free_cnt--;\n-\tnb_descs++;\n-\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n-\t\tvq->vq_avail_idx -= vq->vq_nentries;\n-\t\tvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;\n-\t}\n-\n-\tfor (k = 0; k < pkt_num; k++) {\n-\t\tdesc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem\n-\t\t\t+ sizeof(struct virtio_net_ctrl_hdr)\n-\t\t\t+ sizeof(ctrl->status) + sizeof(uint8_t) * sum;\n-\t\tdesc[vq->vq_avail_idx].len = dlen[k];\n-\t\tdesc[vq->vq_avail_idx].flags = VRING_DESC_F_NEXT |\n-\t\t\tvq->vq_packed.cached_flags;\n-\t\tsum += dlen[k];\n-\t\tvq->vq_free_cnt--;\n-\t\tnb_descs++;\n-\t\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n-\t\t\tvq->vq_avail_idx -= vq->vq_nentries;\n-\t\t\tvq->vq_packed.cached_flags ^=\n-\t\t\t\tVRING_PACKED_DESC_F_AVAIL_USED;\n-\t\t}\n-\t}\n-\n-\tdesc[vq->vq_avail_idx].addr = cvq->virtio_net_hdr_mem\n-\t\t+ sizeof(struct virtio_net_ctrl_hdr);\n-\tdesc[vq->vq_avail_idx].len = sizeof(ctrl->status);\n-\tdesc[vq->vq_avail_idx].flags = VRING_DESC_F_WRITE |\n-\t\tvq->vq_packed.cached_flags;\n-\tvq->vq_free_cnt--;\n-\tnb_descs++;\n-\tif (++vq->vq_avail_idx >= vq->vq_nentries) {\n-\t\tvq->vq_avail_idx -= vq->vq_nentries;\n-\t\tvq->vq_packed.cached_flags ^= VRING_PACKED_DESC_F_AVAIL_USED;\n-\t}\n-\n-\tvirtqueue_store_flags_packed(&desc[head], VRING_DESC_F_NEXT | flags,\n-\t\t\tvq->hw->weak_barriers);\n-\n-\tvirtio_wmb(vq->hw->weak_barriers);\n-\tvirtqueue_notify(vq);\n-\n-\t/* wait for used desc in virtqueue\n-\t * desc_is_used has a load-acquire or rte_io_rmb inside\n-\t */\n-\twhile (!desc_is_used(&desc[head], vq))\n-\t\tusleep(100);\n-\n-\t/* now get used descriptors */\n-\tvq->vq_free_cnt += nb_descs;\n-\tvq->vq_used_cons_idx += nb_descs;\n-\tif (vq->vq_used_cons_idx >= vq->vq_nentries) {\n-\t\tvq->vq_used_cons_idx -= vq->vq_nentries;\n-\t\tvq->vq_packed.used_wrap_counter ^= 1;\n-\t}\n-\n-\tPMD_INIT_LOG(DEBUG, \"vq->vq_free_cnt=%d\\n\"\n-\t\t\t\"vq->vq_avail_idx=%d\\n\"\n-\t\t\t\"vq->vq_used_cons_idx=%d\\n\"\n-\t\t\t\"vq->vq_packed.cached_flags=0x%x\\n\"\n-\t\t\t\"vq->vq_packed.used_wrap_counter=%d\",\n-\t\t\tvq->vq_free_cnt,\n-\t\t\tvq->vq_avail_idx,\n-\t\t\tvq->vq_used_cons_idx,\n-\t\t\tvq->vq_packed.cached_flags,\n-\t\t\tvq->vq_packed.used_wrap_counter);\n-\n-\tresult = cvq->virtio_net_hdr_mz->addr;\n-\treturn result;\n-}\n-\n-static struct virtio_pmd_ctrl *\n-virtio_send_command_split(struct virtnet_ctl *cvq,\n-\t\t\t  struct virtio_pmd_ctrl *ctrl,\n-\t\t\t  int *dlen, int pkt_num)\n-{\n-\tstruct virtio_pmd_ctrl *result;\n-\tstruct virtqueue *vq = virtnet_cq_to_vq(cvq);\n-\tuint32_t head, i;\n-\tint k, sum = 0;\n-\n-\thead = vq->vq_desc_head_idx;\n-\n-\t/*\n-\t * Format is enforced in qemu code:\n-\t * One TX packet for header;\n-\t * At least one TX packet per argument;\n-\t * One RX packet for ACK.\n-\t */\n-\tvq->vq_split.ring.desc[head].flags = VRING_DESC_F_NEXT;\n-\tvq->vq_split.ring.desc[head].addr = cvq->virtio_net_hdr_mem;\n-\tvq->vq_split.ring.desc[head].len = sizeof(struct virtio_net_ctrl_hdr);\n-\tvq->vq_free_cnt--;\n-\ti = vq->vq_split.ring.desc[head].next;\n-\n-\tfor (k = 0; k < pkt_num; k++) {\n-\t\tvq->vq_split.ring.desc[i].flags = VRING_DESC_F_NEXT;\n-\t\tvq->vq_split.ring.desc[i].addr = cvq->virtio_net_hdr_mem\n-\t\t\t+ sizeof(struct virtio_net_ctrl_hdr)\n-\t\t\t+ sizeof(ctrl->status) + sizeof(uint8_t)*sum;\n-\t\tvq->vq_split.ring.desc[i].len = dlen[k];\n-\t\tsum += dlen[k];\n-\t\tvq->vq_free_cnt--;\n-\t\ti = vq->vq_split.ring.desc[i].next;\n-\t}\n-\n-\tvq->vq_split.ring.desc[i].flags = VRING_DESC_F_WRITE;\n-\tvq->vq_split.ring.desc[i].addr = cvq->virtio_net_hdr_mem\n-\t\t\t+ sizeof(struct virtio_net_ctrl_hdr);\n-\tvq->vq_split.ring.desc[i].len = sizeof(ctrl->status);\n-\tvq->vq_free_cnt--;\n-\n-\tvq->vq_desc_head_idx = vq->vq_split.ring.desc[i].next;\n-\n-\tvq_update_avail_ring(vq, head);\n-\tvq_update_avail_idx(vq);\n-\n-\tPMD_INIT_LOG(DEBUG, \"vq->vq_queue_index = %d\", vq->vq_queue_index);\n-\n-\tvirtqueue_notify(vq);\n-\n-\twhile (virtqueue_nused(vq) == 0)\n-\t\tusleep(100);\n-\n-\twhile (virtqueue_nused(vq)) {\n-\t\tuint32_t idx, desc_idx, used_idx;\n-\t\tstruct vring_used_elem *uep;\n-\n-\t\tused_idx = (uint32_t)(vq->vq_used_cons_idx\n-\t\t\t\t& (vq->vq_nentries - 1));\n-\t\tuep = &vq->vq_split.ring.used->ring[used_idx];\n-\t\tidx = (uint32_t) uep->id;\n-\t\tdesc_idx = idx;\n-\n-\t\twhile (vq->vq_split.ring.desc[desc_idx].flags &\n-\t\t\t\tVRING_DESC_F_NEXT) {\n-\t\t\tdesc_idx = vq->vq_split.ring.desc[desc_idx].next;\n-\t\t\tvq->vq_free_cnt++;\n-\t\t}\n-\n-\t\tvq->vq_split.ring.desc[desc_idx].next = vq->vq_desc_head_idx;\n-\t\tvq->vq_desc_head_idx = idx;\n-\n-\t\tvq->vq_used_cons_idx++;\n-\t\tvq->vq_free_cnt++;\n-\t}\n-\n-\tPMD_INIT_LOG(DEBUG, \"vq->vq_free_cnt=%d\\nvq->vq_desc_head_idx=%d\",\n-\t\t\tvq->vq_free_cnt, vq->vq_desc_head_idx);\n-\n-\tresult = cvq->virtio_net_hdr_mz->addr;\n-\treturn result;\n-}\n-\n-static int\n-virtio_send_command(struct virtnet_ctl *cvq, struct virtio_pmd_ctrl *ctrl,\n-\t\t    int *dlen, int pkt_num)\n-{\n-\tvirtio_net_ctrl_ack status = ~0;\n-\tstruct virtio_pmd_ctrl *result;\n-\tstruct virtqueue *vq;\n-\n-\tctrl->status = status;\n-\n-\tif (!cvq) {\n-\t\tPMD_INIT_LOG(ERR, \"Control queue is not supported.\");\n-\t\treturn -1;\n-\t}\n-\n-\trte_spinlock_lock(&cvq->lock);\n-\tvq = virtnet_cq_to_vq(cvq);\n-\n-\tPMD_INIT_LOG(DEBUG, \"vq->vq_desc_head_idx = %d, status = %d, \"\n-\t\t\"vq->hw->cvq = %p vq = %p\",\n-\t\tvq->vq_desc_head_idx, status, vq->hw->cvq, vq);\n-\n-\tif (vq->vq_free_cnt < pkt_num + 2 || pkt_num < 1) {\n-\t\trte_spinlock_unlock(&cvq->lock);\n-\t\treturn -1;\n-\t}\n-\n-\tmemcpy(cvq->virtio_net_hdr_mz->addr, ctrl,\n-\t\tsizeof(struct virtio_pmd_ctrl));\n-\n-\tif (virtio_with_packed_queue(vq->hw))\n-\t\tresult = virtio_send_command_packed(cvq, ctrl, dlen, pkt_num);\n-\telse\n-\t\tresult = virtio_send_command_split(cvq, ctrl, dlen, pkt_num);\n-\n-\trte_spinlock_unlock(&cvq->lock);\n-\treturn result->status;\n-}\n-\n static int\n virtio_set_multiple_queues_rss(struct rte_eth_dev *dev, uint16_t nb_queues)\n {\ndiff --git a/drivers/net/virtio/virtio_rxtx.h b/drivers/net/virtio/virtio_rxtx.h\nindex 6ce5d67d15..6ee3a13100 100644\n--- a/drivers/net/virtio/virtio_rxtx.h\n+++ b/drivers/net/virtio/virtio_rxtx.h\n@@ -46,15 +46,6 @@ struct virtnet_tx {\n \tconst struct rte_memzone *mz;    /**< mem zone to populate TX ring. */\n };\n \n-struct virtnet_ctl {\n-\t/**< memzone to populate hdr. */\n-\tconst struct rte_memzone *virtio_net_hdr_mz;\n-\trte_iova_t virtio_net_hdr_mem;  /**< hdr for each xmit packet */\n-\tuint16_t port_id;               /**< Device port identifier. */\n-\tconst struct rte_memzone *mz;   /**< mem zone to populate CTL ring. */\n-\trte_spinlock_t lock;              /**< spinlock for control queue. */\n-};\n-\n int virtio_rxq_vec_setup(struct virtnet_rx *rxvq);\n void virtio_update_packet_stats(struct virtnet_stats *stats,\n \t\t\t\tstruct rte_mbuf *mbuf);\ndiff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h\nindex f5d8b40cad..62f472850e 100644\n--- a/drivers/net/virtio/virtqueue.h\n+++ b/drivers/net/virtio/virtqueue.h\n@@ -16,6 +16,7 @@\n #include \"virtio_ring.h\"\n #include \"virtio_logs.h\"\n #include \"virtio_rxtx.h\"\n+#include \"virtio_cvq.h\"\n \n struct rte_mbuf;\n \n@@ -145,113 +146,9 @@ enum { VTNET_RQ = 0, VTNET_TQ = 1, VTNET_CQ = 2 };\n  */\n #define VQ_RING_DESC_CHAIN_END 32768\n \n-/**\n- * Control the RX mode, ie. promiscuous, allmulti, etc...\n- * All commands require an \"out\" sg entry containing a 1 byte\n- * state value, zero = disable, non-zero = enable.  Commands\n- * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature.\n- * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA.\n- */\n-#define VIRTIO_NET_CTRL_RX              0\n-#define VIRTIO_NET_CTRL_RX_PROMISC      0\n-#define VIRTIO_NET_CTRL_RX_ALLMULTI     1\n-#define VIRTIO_NET_CTRL_RX_ALLUNI       2\n-#define VIRTIO_NET_CTRL_RX_NOMULTI      3\n-#define VIRTIO_NET_CTRL_RX_NOUNI        4\n-#define VIRTIO_NET_CTRL_RX_NOBCAST      5\n-\n-/**\n- * Control the MAC\n- *\n- * The MAC filter table is managed by the hypervisor, the guest should\n- * assume the size is infinite.  Filtering should be considered\n- * non-perfect, ie. based on hypervisor resources, the guest may\n- * received packets from sources not specified in the filter list.\n- *\n- * In addition to the class/cmd header, the TABLE_SET command requires\n- * two out scatterlists.  Each contains a 4 byte count of entries followed\n- * by a concatenated byte stream of the ETH_ALEN MAC addresses.  The\n- * first sg list contains unicast addresses, the second is for multicast.\n- * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature\n- * is available.\n- *\n- * The ADDR_SET command requests one out scatterlist, it contains a\n- * 6 bytes MAC address. This functionality is present if the\n- * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available.\n- */\n-struct virtio_net_ctrl_mac {\n-\tuint32_t entries;\n-\tuint8_t macs[][RTE_ETHER_ADDR_LEN];\n-} __rte_packed;\n-\n-#define VIRTIO_NET_CTRL_MAC    1\n-#define VIRTIO_NET_CTRL_MAC_TABLE_SET        0\n-#define VIRTIO_NET_CTRL_MAC_ADDR_SET         1\n-\n-/**\n- * Control VLAN filtering\n- *\n- * The VLAN filter table is controlled via a simple ADD/DEL interface.\n- * VLAN IDs not added may be filtered by the hypervisor.  Del is the\n- * opposite of add.  Both commands expect an out entry containing a 2\n- * byte VLAN ID.  VLAN filtering is available with the\n- * VIRTIO_NET_F_CTRL_VLAN feature bit.\n- */\n-#define VIRTIO_NET_CTRL_VLAN     2\n-#define VIRTIO_NET_CTRL_VLAN_ADD 0\n-#define VIRTIO_NET_CTRL_VLAN_DEL 1\n-\n-/**\n- * RSS control\n- *\n- * The RSS feature configuration message is sent by the driver when\n- * VIRTIO_NET_F_RSS has been negotiated. It provides the device with\n- * hash types to use, hash key and indirection table. In this\n- * implementation, the driver only supports fixed key length (40B)\n- * and indirection table size (128 entries).\n- */\n-#define VIRTIO_NET_RSS_RETA_SIZE 128\n-#define VIRTIO_NET_RSS_KEY_SIZE 40\n-\n-struct virtio_net_ctrl_rss {\n-\tuint32_t hash_types;\n-\tuint16_t indirection_table_mask;\n-\tuint16_t unclassified_queue;\n-\tuint16_t indirection_table[VIRTIO_NET_RSS_RETA_SIZE];\n-\tuint16_t max_tx_vq;\n-\tuint8_t hash_key_length;\n-\tuint8_t hash_key_data[VIRTIO_NET_RSS_KEY_SIZE];\n-};\n-\n-/*\n- * Control link announce acknowledgement\n- *\n- * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that\n- * driver has received the notification; device would clear the\n- * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives\n- * this command.\n- */\n-#define VIRTIO_NET_CTRL_ANNOUNCE     3\n-#define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0\n-\n-struct virtio_net_ctrl_hdr {\n-\tuint8_t class;\n-\tuint8_t cmd;\n-} __rte_packed;\n-\n-typedef uint8_t virtio_net_ctrl_ack;\n-\n #define VIRTIO_NET_OK     0\n #define VIRTIO_NET_ERR    1\n \n-#define VIRTIO_MAX_CTRL_DATA 2048\n-\n-struct virtio_pmd_ctrl {\n-\tstruct virtio_net_ctrl_hdr hdr;\n-\tvirtio_net_ctrl_ack status;\n-\tuint8_t data[VIRTIO_MAX_CTRL_DATA];\n-};\n-\n struct vq_desc_extra {\n \tvoid *cookie;\n \tuint16_t ndescs;\n",
    "prefixes": [
        "v2",
        "01/21"
    ]
}