From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by dpdk.org (Postfix) with ESMTP id 70C8E558D for ; Mon, 13 Jun 2016 08:44:01 +0200 (CEST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 12 Jun 2016 23:44:01 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,465,1459839600"; d="scan'208";a="986195209" Received: from dpdk06.sh.intel.com ([10.239.128.225]) by fmsmga001.fm.intel.com with ESMTP; 12 Jun 2016 23:43:59 -0700 From: Jianfeng Tan To: dev@dpdk.org Cc: Jianfeng Tan , rich.lane@bigswitch.com, yuanhan.liu@linux.intel.com, mst@redhat.com, nakajima.yoshihiro@lab.ntt.co.jp, p.fedin@samsung.com, ann.zhuangyanying@huawei.com, mukawa@igel.co.jp, nhorman@tuxdriver.com Date: Mon, 13 Jun 2016 06:43:42 +0000 Message-Id: <1465800223-139122-4-git-send-email-jianfeng.tan@intel.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1465800223-139122-1-git-send-email-jianfeng.tan@intel.com> References: <1462438781-139674-1-git-send-email-jianfeng.tan@intel.com> <1465800223-139122-1-git-send-email-jianfeng.tan@intel.com> Subject: [dpdk-dev] [PATCH v2 3/4] virtio-user: add ctrl-q and mq in device emulation X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jun 2016 06:44:02 -0000 The main purpose of this patch is to enable multi-queue. But multi-queue requires ctrl-queue so that driver can send how many queues will be enabled through ctrl-queue messages. So we partially implement ctrl-queue to handle control command with class of VIRTIO_NET_CTRL_MQ and with cmd of VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET to handle mq support. This patch provides an API, virtio_user_handle_cq(), for driver to handle ctrl-queue messages. Besides, multi-queue requires VIRTIO_NET_F_MQ and VIRTIO_NET_F_CTRL_VQ are enabled when we do feature negotiation. Signed-off-by: Jianfeng Tan --- drivers/net/virtio/virtio_user/virtio_user_dev.c | 124 +++++++++++++++++++++-- drivers/net/virtio/virtio_user/virtio_user_dev.h | 2 +- 2 files changed, 116 insertions(+), 10 deletions(-) diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.c b/drivers/net/virtio/virtio_user/virtio_user_dev.c index 93cb758..3c72a2a 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.c +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.c @@ -131,11 +131,14 @@ virtio_user_start_device(struct virtio_user_dev *dev) } } - /* After setup all virtqueues, we need to set_features so that - * these features can be set into each virtqueue in vhost side. - * And before that, make sure VIRTIO_NET_F_MAC is stripped. + /* After setup all virtqueues, we need to set_features so that these + * features can be set into each virtqueue in vhost side. And before + * that, make sure VHOST_USER_F_PROTOCOL_FEATURES is added if mq is + * enabled, and VIRTIO_NET_F_MAC is stripped. */ features = dev->features; + if (dev->max_queue_pairs > 1) + features |= VHOST_USER_MQ; features &= ~(1ull << VIRTIO_NET_F_MAC); ret = vhost_user_sock(dev->vhostfd, VHOST_USER_SET_FEATURES, &features); if (ret < 0) @@ -185,8 +188,6 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues, dev->mac_specified = 0; parse_mac(dev, mac); dev->vhostfd = -1; - /* TODO: cq */ - RTE_SET_USED(cq); dev->vhostfd = vhost_user_setup(dev->path); if (dev->vhostfd < 0) { @@ -205,12 +206,33 @@ virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues, } if (dev->mac_specified) dev->features |= (1ull << VIRTIO_NET_F_MAC); - /* disable it until we support CQ */ - dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ); - dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_RX); - return 0; + if (!cq) { + dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_VQ); + /* Also disable features depends on VIRTIO_NET_F_CTRL_VQ */ + dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_RX); + dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_VLAN); + dev->features &= ~(1ull << VIRTIO_NET_F_GUEST_ANNOUNCE); + dev->features &= ~(1ull << VIRTIO_NET_F_MQ); + dev->features &= ~(1ull << VIRTIO_NET_F_CTRL_MAC_ADDR); + } else { + /* vhost user backend does not need to know ctrl-q, so + * actually we need add this bit into features. However, + * DPDK vhost-user does send features with this bit, so we + * check it instead of OR it for now. + */ + if (!(dev->features & (1ull << VIRTIO_NET_F_CTRL_VQ))) + PMD_INIT_LOG(INFO, "vhost does not support ctrl-q"); + } + + if (dev->max_queue_pairs > 1) { + if (!(dev->features & VHOST_USER_MQ)) { + PMD_INIT_LOG(ERR, "MQ not supported by the backend"); + return -1; + } + } + return 0; } void @@ -225,3 +247,87 @@ virtio_user_dev_uninit(struct virtio_user_dev *dev) close(dev->vhostfd); } + +static uint8_t +virtio_user_handle_mq(struct virtio_user_dev *dev, uint16_t q_pairs) +{ + uint16_t i; + uint8_t ret = 0; + + if (q_pairs > dev->max_queue_pairs) { + PMD_INIT_LOG(ERR, "multi-q config %u, but only %u supported", + q_pairs, dev->max_queue_pairs); + return -1; + } + + for (i = 0; i < q_pairs; ++i) + ret |= vhost_user_enable_queue_pair(dev->vhostfd, i, 1); + for (i = q_pairs; i < dev->max_queue_pairs; ++i) + ret |= vhost_user_enable_queue_pair(dev->vhostfd, i, 0); + + dev->queue_pairs = q_pairs; + + return ret; +} + +static uint32_t +virtio_user_handle_ctrl_msg(struct virtio_user_dev *dev, struct vring *vring, + uint16_t desc_idx_hdr) +{ + struct virtio_net_ctrl_hdr *hdr; + virtio_net_ctrl_ack status = ~0; + uint16_t i, desc_idx_data, desc_idx_status; + uint32_t n_descs = 0; + + /* locate desc for header, data, and status */ + desc_idx_data = vring->desc[desc_idx_hdr].next; + n_descs++; + + i = desc_idx_data; + while (vring->desc[i].flags == VRING_DESC_F_NEXT) { + i = vring->desc[i].next; + n_descs++; + } + + /* locate desc for status */ + desc_idx_status = i; + n_descs++; + + hdr = (struct virtio_net_ctrl_hdr *)vring->desc[desc_idx_hdr].addr; + if (hdr->class == VIRTIO_NET_CTRL_MQ && + hdr->cmd == VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET) { + uint16_t queues; + + queues = *(uint16_t *)vring->desc[desc_idx_data].addr; + status = virtio_user_handle_mq(dev, queues); + } + + /* Update status */ + *(virtio_net_ctrl_ack *)vring->desc[desc_idx_status].addr = status; + + return n_descs; +} + +void +virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx) +{ + uint16_t avail_idx, desc_idx; + struct vring_used_elem *uep; + uint32_t n_descs; + struct vring *vring = &dev->vrings[queue_idx]; + + /* Consume avail ring, using used ring idx as first one */ + while (vring->used->idx != vring->avail->idx) { + avail_idx = (vring->used->idx) & (vring->num - 1); + desc_idx = vring->avail->ring[avail_idx]; + + n_descs = virtio_user_handle_ctrl_msg(dev, vring, desc_idx); + + /* Update used ring */ + uep = &vring->used->ring[avail_idx]; + uep->id = avail_idx; + uep->len = n_descs; + + vring->used->idx++; + } +} diff --git a/drivers/net/virtio/virtio_user/virtio_user_dev.h b/drivers/net/virtio/virtio_user/virtio_user_dev.h index 68bee37..33690b5 100644 --- a/drivers/net/virtio/virtio_user/virtio_user_dev.h +++ b/drivers/net/virtio/virtio_user/virtio_user_dev.h @@ -58,5 +58,5 @@ int virtio_user_stop_device(struct virtio_user_dev *dev); int virtio_user_dev_init(struct virtio_user_dev *dev, char *path, int queues, int cq, int queue_size, const char *mac); void virtio_user_dev_uninit(struct virtio_user_dev *dev); - +void virtio_user_handle_cq(struct virtio_user_dev *dev, uint16_t queue_idx); #endif -- 2.1.4