DPDK patches and discussions
 help / color / mirror / Atom feed
From: Yuanhan Liu <yuanhan.liu@linux.intel.com>
To: "Ouyang, Changchun" <changchun.ouyang@intel.com>
Cc: "dev@dpdk.org" <dev@dpdk.org>
Subject: Re: [dpdk-dev] [PATCH v4 02/12] vhost: support multiple queues in virtio dev
Date: Wed, 19 Aug 2015 14:28:51 +0800	[thread overview]
Message-ID: <20150819062851.GB2438@yliu-dev.sh.intel.com> (raw)
In-Reply-To: <F52918179C57134FAEC9EA62FA2F962511CCC8A5@shsmsx102.ccr.corp.intel.com>

On Wed, Aug 19, 2015 at 05:54:09AM +0000, Ouyang, Changchun wrote:
> Hi Yuanhan,
> 
> > -----Original Message-----
> > From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> > Sent: Wednesday, August 19, 2015 11:53 AM
> > To: Ouyang, Changchun
> > Cc: dev@dpdk.org; Xie, Huawei
> > Subject: Re: [dpdk-dev] [PATCH v4 02/12] vhost: support multiple queues in
> > virtio dev
> > 
> > Hi Changchun,
> > 
> > On Wed, Aug 12, 2015 at 04:02:37PM +0800, Ouyang Changchun wrote:
> > > Each virtio device could have multiple queues, say 2 or 4, at most 8.
> > > Enabling this feature allows virtio device/port on guest has the
> > > ability to use different vCPU to receive/transmit packets from/to each
> > queue.
> > >
> > > In multiple queues mode, virtio device readiness means all queues of
> > > this virtio device are ready, cleanup/destroy a virtio device also
> > > requires clearing all queues belong to it.
> > >
> > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > ---
> > [snip ..]
> > >  /*
> > > + *  Initialise all variables in vring queue pair.
> > > + */
> > > +static void
> > > +init_vring_queue_pair(struct virtio_net *dev, uint16_t qp_idx) {
> > > +	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
> > > +	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
> > > +	memset(dev->virtqueue[virt_rx_q_idx], 0, sizeof(struct
> > vhost_virtqueue));
> > > +	memset(dev->virtqueue[virt_tx_q_idx], 0, sizeof(struct
> > > +vhost_virtqueue));
> > > +
> > > +	dev->virtqueue[virt_rx_q_idx]->kickfd = (eventfd_t)-1;
> > > +	dev->virtqueue[virt_rx_q_idx]->callfd = (eventfd_t)-1;
> > > +	dev->virtqueue[virt_tx_q_idx]->kickfd = (eventfd_t)-1;
> > > +	dev->virtqueue[virt_tx_q_idx]->callfd = (eventfd_t)-1;
> > > +
> > > +	/* Backends are set to -1 indicating an inactive device. */
> > > +	dev->virtqueue[virt_rx_q_idx]->backend = VIRTIO_DEV_STOPPED;
> > > +	dev->virtqueue[virt_tx_q_idx]->backend = VIRTIO_DEV_STOPPED; }
> > > +
> > > +/*
> > >   *  Initialise all variables in device structure.
> > >   */
> > >  static void
> > > @@ -258,17 +294,34 @@ init_device(struct virtio_net *dev)
> > >  	/* Set everything to 0. */
> > 
> > There is a trick here. Let me fill the context first:
> > 
> > 283 static void
> > 284 init_device(struct virtio_net *dev)
> > 285 {
> > 286         uint64_t vq_offset;
> > 287
> > 288         /*
> > 289          * Virtqueues have already been malloced so
> > 290          * we don't want to set them to NULL.
> > 291          */
> > 292         vq_offset = offsetof(struct virtio_net, mem);
> > 293
> > 294         /* Set everything to 0. */
> > 295         memset((void *)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0,
> > 296                 (sizeof(struct virtio_net) - (size_t)vq_offset));
> > 297
> > 298         init_vring_queue_pair(dev, 0);
> > 
> > This piece of code's intention is to memset everything to zero, except the
> > `virtqueue' field, for, as the comment stated, we have already allocated
> > virtqueue.
> > 
> > It works only when `virtqueue' field is before `mem' field, and it was
> > before:
> > 
> >     struct virtio_net {
> >             struct vhost_virtqueue  *virtqueue[VIRTIO_QNUM];        /**< Contains
> > all virtqueue information. */
> >             struct virtio_memory    *mem;           /**< QEMU memory and memory
> > region information. */
> >             ...
> > 
> > After this patch, it becomes:
> > 
> >     struct virtio_net {
> >             struct virtio_memory    *mem;           /**< QEMU memory and memory
> > region information. */
> >             struct vhost_virtqueue  **virtqueue;    /**< Contains all virtqueue
> > information. */
> >             ...
> > 
> > 
> > Which actually wipes all stuff inside `struct virtio_net`, resulting to setting
> > `virtqueue' to NULL as well.
> > 
> > While reading the code(without you patch applied), I thought that it's error-
> > prone, as it is very likely that someone else besides the author doesn't know
> > such undocumented rule. And you just gave me an example :)
> > 
> > Huawei, I'm proposing a fix to call rte_zmalloc() for allocating new_ll_dev to
> > get rid of such issue. What do you think?
> > 
> > 	--yliu
> > 
> > 
> 
> Suggest you finish the latter patch review:
> [PATCH v4 04/12] vhost: set memory layout for multiple queues mode,
> After you finish reviewing this patch, I think you will change your mind :-)
> 
> This patch resolve what you concern.

Sorry that I hadn't gone that far yet. And yes, I see. I found that you
moved the barrier to `features' field, which puts the `virtqueue' field
back to the "do not set to zero" zone.

It's still an undocumented rule, and hence, error prone, IMO. But, you
reminded me that init_device() will be invoked at other place else(reset_owner()).
Hence, my solution won't work, either.

I'm wondering saving the `virtqueue'(and `mem_arr' from patch 04/12)
explicitly before memset() and restoring them after that, to get rid of
the undocumented rule. It may become uglier with more and more fields
need to be saved this way. But judging that we have two fields so far,
I'm kind of okay to that.

What do you think then? If that doesn't work, we should add some comments
inside the virtio_net struct at least, or even add a build time check.

	--yliu

> > 
> > >  	memset((void *)(uintptr_t)((uint64_t)(uintptr_t)dev + vq_offset), 0,
> > >  		(sizeof(struct virtio_net) - (size_t)vq_offset));
> > > -	memset(dev->virtqueue[VIRTIO_RXQ], 0, sizeof(struct
> > vhost_virtqueue));
> > > -	memset(dev->virtqueue[VIRTIO_TXQ], 0, sizeof(struct
> > vhost_virtqueue));
> > >
> > > -	dev->virtqueue[VIRTIO_RXQ]->kickfd = (eventfd_t)-1;
> > > -	dev->virtqueue[VIRTIO_RXQ]->callfd = (eventfd_t)-1;
> > > -	dev->virtqueue[VIRTIO_TXQ]->kickfd = (eventfd_t)-1;
> > > -	dev->virtqueue[VIRTIO_TXQ]->callfd = (eventfd_t)-1;
> > > +	init_vring_queue_pair(dev, 0);
> > > +	dev->virt_qp_nb = 1;
> > > +}
> > > +
> > > +/*
> > > + *  Alloc mem for vring queue pair.
> > > + */
> > > +int
> > > +alloc_vring_queue_pair(struct virtio_net *dev, uint16_t qp_idx) {
> > > +	struct vhost_virtqueue *virtqueue = NULL;
> > > +	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
> > > +	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
> > >
> > > -	/* Backends are set to -1 indicating an inactive device. */
> > > -	dev->virtqueue[VIRTIO_RXQ]->backend = VIRTIO_DEV_STOPPED;
> > > -	dev->virtqueue[VIRTIO_TXQ]->backend = VIRTIO_DEV_STOPPED;
> > > +	virtqueue = rte_malloc(NULL, sizeof(struct vhost_virtqueue) *
> > VIRTIO_QNUM, 0);
> > > +	if (virtqueue == NULL) {
> > > +		RTE_LOG(ERR, VHOST_CONFIG,
> > > +			"Failed to allocate memory for virt qp:%d.\n",
> > qp_idx);
> > > +		return -1;
> > > +	}
> > > +
> > > +	dev->virtqueue[virt_rx_q_idx] = virtqueue;
> > > +	dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
> > > +
> > > +	init_vring_queue_pair(dev, qp_idx);
> > > +
> > > +	return 0;
> > >  }
> > >
> > >  /*
> > > @@ -280,7 +333,6 @@ static int
> > >  new_device(struct vhost_device_ctx ctx)  {
> > >  	struct virtio_net_config_ll *new_ll_dev;
> > > -	struct vhost_virtqueue *virtqueue_rx, *virtqueue_tx;
> > >
> > >  	/* Setup device and virtqueues. */
> > >  	new_ll_dev = rte_malloc(NULL, sizeof(struct virtio_net_config_ll),
> > > 0); @@ -291,28 +343,22 @@ new_device(struct vhost_device_ctx ctx)
> > >  		return -1;
> > >  	}
> > >
> > > -	virtqueue_rx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
> > > -	if (virtqueue_rx == NULL) {
> > > -		rte_free(new_ll_dev);
> > > +	new_ll_dev->dev.virtqueue =
> > > +		rte_malloc(NULL, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX *
> > sizeof(struct vhost_virtqueue *), 0);
> > > +	if (new_ll_dev->dev.virtqueue == NULL) {
> > >  		RTE_LOG(ERR, VHOST_CONFIG,
> > > -			"(%"PRIu64") Failed to allocate memory for rxq.\n",
> > > +			"(%"PRIu64") Failed to allocate memory for
> > dev.virtqueue.\n",
> > >  			ctx.fh);
> > > +		rte_free(new_ll_dev);
> > >  		return -1;
> > >  	}
> > >
> > > -	virtqueue_tx = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
> > > -	if (virtqueue_tx == NULL) {
> > > -		rte_free(virtqueue_rx);
> > > +	if (alloc_vring_queue_pair(&new_ll_dev->dev, 0) == -1) {
> > > +		rte_free(new_ll_dev->dev.virtqueue);
> > >  		rte_free(new_ll_dev);
> > > -		RTE_LOG(ERR, VHOST_CONFIG,
> > > -			"(%"PRIu64") Failed to allocate memory for txq.\n",
> > > -			ctx.fh);
> > >  		return -1;
> > >  	}
> > >
> > > -	new_ll_dev->dev.virtqueue[VIRTIO_RXQ] = virtqueue_rx;
> > > -	new_ll_dev->dev.virtqueue[VIRTIO_TXQ] = virtqueue_tx;
> > > -
> > >  	/* Initialise device and virtqueues. */
> > >  	init_device(&new_ll_dev->dev);
> > >
> > > @@ -396,7 +442,7 @@ set_owner(struct vhost_device_ctx ctx)
> > >   * Called from CUSE IOCTL: VHOST_RESET_OWNER
> > >   */
> > >  static int
> > > -reset_owner(struct vhost_device_ctx ctx)
> > > +reset_owner(__rte_unused struct vhost_device_ctx ctx)
> > >  {
> > >  	struct virtio_net_config_ll *ll_dev;
> > >
> > > @@ -434,6 +480,7 @@ static int
> > >  set_features(struct vhost_device_ctx ctx, uint64_t *pu)  {
> > >  	struct virtio_net *dev;
> > > +	uint32_t q_idx;
> > >
> > >  	dev = get_device(ctx);
> > >  	if (dev == NULL)
> > > @@ -445,22 +492,26 @@ set_features(struct vhost_device_ctx ctx,
> > uint64_t *pu)
> > >  	dev->features = *pu;
> > >
> > >  	/* Set the vhost_hlen depending on if VIRTIO_NET_F_MRG_RXBUF
> > is set. */
> > > -	if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
> > > -		LOG_DEBUG(VHOST_CONFIG,
> > > -			"(%"PRIu64") Mergeable RX buffers enabled\n",
> > > -			dev->device_fh);
> > > -		dev->virtqueue[VIRTIO_RXQ]->vhost_hlen =
> > > -			sizeof(struct virtio_net_hdr_mrg_rxbuf);
> > > -		dev->virtqueue[VIRTIO_TXQ]->vhost_hlen =
> > > -			sizeof(struct virtio_net_hdr_mrg_rxbuf);
> > > -	} else {
> > > -		LOG_DEBUG(VHOST_CONFIG,
> > > -			"(%"PRIu64") Mergeable RX buffers disabled\n",
> > > -			dev->device_fh);
> > > -		dev->virtqueue[VIRTIO_RXQ]->vhost_hlen =
> > > -			sizeof(struct virtio_net_hdr);
> > > -		dev->virtqueue[VIRTIO_TXQ]->vhost_hlen =
> > > -			sizeof(struct virtio_net_hdr);
> > > +	for (q_idx = 0; q_idx < dev->virt_qp_nb; q_idx++) {
> > > +		uint32_t virt_rx_q_idx = q_idx * VIRTIO_QNUM +
> > VIRTIO_RXQ;
> > > +		uint32_t virt_tx_q_idx = q_idx * VIRTIO_QNUM +
> > VIRTIO_TXQ;
> > > +		if (dev->features & (1 << VIRTIO_NET_F_MRG_RXBUF)) {
> > > +			LOG_DEBUG(VHOST_CONFIG,
> > > +				"(%"PRIu64") Mergeable RX buffers
> > enabled\n",
> > > +				dev->device_fh);
> > > +			dev->virtqueue[virt_rx_q_idx]->vhost_hlen =
> > > +				sizeof(struct virtio_net_hdr_mrg_rxbuf);
> > > +			dev->virtqueue[virt_tx_q_idx]->vhost_hlen =
> > > +				sizeof(struct virtio_net_hdr_mrg_rxbuf);
> > > +		} else {
> > > +			LOG_DEBUG(VHOST_CONFIG,
> > > +				"(%"PRIu64") Mergeable RX buffers
> > disabled\n",
> > > +				dev->device_fh);
> > > +			dev->virtqueue[virt_rx_q_idx]->vhost_hlen =
> > > +				sizeof(struct virtio_net_hdr);
> > > +			dev->virtqueue[virt_tx_q_idx]->vhost_hlen =
> > > +				sizeof(struct virtio_net_hdr);
> > > +		}
> > >  	}
> > >  	return 0;
> > >  }
> > > @@ -826,6 +877,14 @@ int rte_vhost_feature_enable(uint64_t
> > feature_mask)
> > >  	return -1;
> > >  }
> > >
> > > +uint16_t rte_vhost_qp_num_get(struct virtio_net *dev) {
> > > +	if (dev == NULL)
> > > +		return 0;
> > > +
> > > +	return dev->virt_qp_nb;
> > > +}
> > > +
> > >  /*
> > >   * Register ops so that we can add/remove device to data core.
> > >   */
> > > --
> > > 1.8.4.2
> > >

  reply	other threads:[~2015-08-19  6:28 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-21  7:49 [dpdk-dev] [PATCH 0/6] Support multiple queues in vhost Ouyang Changchun
2015-05-21  7:49 ` [dpdk-dev] [PATCH 1/6] ixgbe: Support VMDq RSS in non-SRIOV environment Ouyang Changchun
2015-08-24 10:41   ` Qiu, Michael
2015-08-25  0:38     ` Ouyang, Changchun
2015-05-21  7:49 ` [dpdk-dev] [PATCH 2/6] lib_vhost: Support multiple queues in virtio dev Ouyang Changchun
2015-06-03  2:47   ` Xie, Huawei
2015-05-21  7:49 ` [dpdk-dev] [PATCH 3/6] lib_vhost: Set memory layout for multiple queues mode Ouyang Changchun
2015-06-02  3:33   ` Xie, Huawei
2015-05-21  7:49 ` [dpdk-dev] [PATCH 4/6] vhost: Add new command line option: rxq Ouyang Changchun
2015-05-22  1:39   ` Thomas F Herbert
2015-05-22  6:05     ` Ouyang, Changchun
2015-05-22 12:51       ` Thomas F Herbert
2015-05-23  1:25         ` Ouyang, Changchun
2015-05-26  7:21           ` Ouyang, Changchun
2015-05-21  7:49 ` [dpdk-dev] [PATCH 5/6] vhost: Support multiple queues Ouyang Changchun
2015-05-21  7:49 ` [dpdk-dev] [PATCH 6/6] virtio: Resolve for control queue Ouyang Changchun
2015-05-22  1:13 ` [dpdk-dev] [PATCH 0/6] Support multiple queues in vhost Thomas F Herbert
2015-05-22  6:08   ` Ouyang, Changchun
2015-06-10  5:52 ` [dpdk-dev] [PATCH v2 0/7] " Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 1/7] ixgbe: Support VMDq RSS in non-SRIOV environment Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 2/7] lib_vhost: Support multiple queues in virtio dev Ouyang Changchun
2015-06-11  9:54     ` Panu Matilainen
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 3/7] lib_vhost: Set memory layout for multiple queues mode Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 4/7] vhost: Add new command line option: rxq Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 5/7] vhost: Support multiple queues Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 6/7] virtio: Resolve for control queue Ouyang Changchun
2015-06-10  5:52   ` [dpdk-dev] [PATCH v2 7/7] vhost: Add per queue stats info Ouyang Changchun
2015-06-15  7:56   ` [dpdk-dev] [PATCH v3 0/9] Support multiple queues in vhost Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 1/9] ixgbe: Support VMDq RSS in non-SRIOV environment Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 2/9] lib_vhost: Support multiple queues in virtio dev Ouyang Changchun
2015-06-18 13:16       ` Flavio Leitner
2015-06-19  1:06         ` Ouyang, Changchun
2015-06-18 13:34       ` Flavio Leitner
2015-06-19  1:17         ` Ouyang, Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 3/9] lib_vhost: Set memory layout for multiple queues mode Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 4/9] lib_vhost: Check the virtqueue address's validity Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 5/9] vhost: Add new command line option: rxq Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 6/9] vhost: Support multiple queues Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 7/9] virtio: Resolve for control queue Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 8/9] vhost: Add per queue stats info Ouyang Changchun
2015-06-15  7:56     ` [dpdk-dev] [PATCH v3 9/9] doc: Update doc for vhost multiple queues Ouyang Changchun
2015-08-12  8:02     ` [dpdk-dev] [PATCH v4 00/12] Support multiple queues in vhost Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 01/12] ixgbe: support VMDq RSS in non-SRIOV environment Ouyang Changchun
2015-08-12  8:22         ` Vincent JARDIN
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 02/12] vhost: support multiple queues in virtio dev Ouyang Changchun
2015-08-13 12:52         ` Flavio Leitner
2015-08-14  2:29           ` Ouyang, Changchun
2015-08-14 12:16             ` Flavio Leitner
2015-08-19  3:52         ` Yuanhan Liu
2015-08-19  5:54           ` Ouyang, Changchun
2015-08-19  6:28             ` Yuanhan Liu [this message]
2015-08-19  6:39               ` Yuanhan Liu
2015-09-03  2:27         ` Tetsuya Mukawa
2015-09-06  2:25           ` Ouyang, Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 03/12] vhost: update version map file Ouyang Changchun
2015-08-12  8:24         ` Panu Matilainen
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 04/12] vhost: set memory layout for multiple queues mode Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 05/12] vhost: check the virtqueue address's validity Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 06/12] vhost: support protocol feature Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 07/12] vhost: add new command line option: rxq Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 08/12] vhost: support multiple queues Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 09/12] virtio: resolve for control queue Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 10/12] vhost: add per queue stats info Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 11/12] vhost: alloc core to virtq Ouyang Changchun
2015-08-12  8:02       ` [dpdk-dev] [PATCH v4 12/12] doc: update doc for vhost multiple queues Ouyang Changchun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150819062851.GB2438@yliu-dev.sh.intel.com \
    --to=yuanhan.liu@linux.intel.com \
    --cc=changchun.ouyang@intel.com \
    --cc=dev@dpdk.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).