All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
@ 2015-05-28  1:23 Ouyang Changchun
  2015-07-08 14:29 ` Michael S. Tsirkin
                   ` (2 more replies)
  0 siblings, 3 replies; 44+ messages in thread
From: Ouyang Changchun @ 2015-05-28  1:23 UTC (permalink / raw)
  To: qemu-devel, mst
  Cc: snabb-devel, n.nikolaev, luke, thomas.long, changchun.ouyang

Based on patch by Nikolay Nikolaev:
Vhost-user will implement the multi queue support in a similar way
to what vhost already has - a separate thread for each queue.
To enable the multi queue functionality - a new command line parameter
"queues" is introduced for the vhost-user netdev.

Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
---
Changes since v4:
 - remove the unnecessary trailing '\n'

Changes since v3:
 - fix one typo and wrap one long line

Changes since v2:
 - fix vq index issue for set_vring_call
   When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
   thus it could be a random value. The random value leads to crash in vhost after passing down
   to vhost, as vhost use this random value to index an array index.
 - fix the typo in the doc and description
 - address vq index for reset_owner

Changes since v1:
 - use s->nc.info_str when bringing up/down the backend

 docs/specs/vhost-user.txt |  5 +++++
 hw/net/vhost_net.c        |  3 ++-
 hw/virtio/vhost-user.c    | 11 ++++++++++-
 net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
 qapi-schema.json          |  6 +++++-
 qemu-options.hx           |  5 +++--
 6 files changed, 49 insertions(+), 18 deletions(-)

diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
index 650bb18..2c8e934 100644
--- a/docs/specs/vhost-user.txt
+++ b/docs/specs/vhost-user.txt
@@ -127,6 +127,11 @@ in the ancillary data:
 If Master is unable to send the full message or receives a wrong reply it will
 close the connection. An optional reconnection mechanism can be implemented.
 
+Multi queue support
+-------------------
+The protocol supports multiple queues by setting all index fields in the sent
+messages to a properly calculated value.
+
 Message types
 -------------
 
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 47f8b89..426b23e 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
 
     net->dev.nvqs = 2;
     net->dev.vqs = net->vqs;
+    net->dev.vq_index = net->nc->queue_index;
 
     r = vhost_dev_init(&net->dev, options->opaque,
                        options->backend_type, options->force);
@@ -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
         for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
             const VhostOps *vhost_ops = net->dev.vhost_ops;
             int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
-                                          NULL);
+                                          &file);
             assert(r >= 0);
         }
     }
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index e7ab829..d6f2163 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
         break;
 
     case VHOST_SET_OWNER:
+        break;
+
     case VHOST_RESET_OWNER:
+        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
+        msg.size = sizeof(m.state);
         break;
 
     case VHOST_SET_MEM_TABLE:
@@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
     case VHOST_SET_VRING_NUM:
     case VHOST_SET_VRING_BASE:
         memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
         msg.size = sizeof(m.state);
         break;
 
     case VHOST_GET_VRING_BASE:
         memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
         msg.size = sizeof(m.state);
         need_reply = 1;
         break;
 
     case VHOST_SET_VRING_ADDR:
         memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
+        msg.addr.index += dev->vq_index;
         msg.size = sizeof(m.addr);
         break;
 
@@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
     case VHOST_SET_VRING_CALL:
     case VHOST_SET_VRING_ERR:
         file = arg;
-        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
+        msg.u64 = (file->index + dev->vq_index) & VHOST_USER_VRING_IDX_MASK;
         msg.size = sizeof(m.u64);
         if (ioeventfd_enabled() && file->fd > 0) {
             fds[fd_num++] = file->fd;
@@ -313,6 +321,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
                 error_report("Received bad msg size.");
                 return -1;
             }
+            msg.state.index -= dev->vq_index;
             memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
             break;
         default:
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 1d86a2b..904d8af 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque, int event)
     case CHR_EVENT_OPENED:
         vhost_user_start(s);
         net_vhost_link_down(s, false);
-        error_report("chardev \"%s\" went up", s->chr->label);
+        error_report("chardev \"%s\" went up", s->nc.info_str);
         break;
     case CHR_EVENT_CLOSED:
         net_vhost_link_down(s, true);
         vhost_user_stop(s);
-        error_report("chardev \"%s\" went down", s->chr->label);
+        error_report("chardev \"%s\" went down", s->nc.info_str);
         break;
     }
 }
 
 static int net_vhost_user_init(NetClientState *peer, const char *device,
-                               const char *name, CharDriverState *chr)
+                               const char *name, CharDriverState *chr,
+                               uint32_t queues)
 {
     NetClientState *nc;
     VhostUserState *s;
+    int i;
 
-    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
+    for (i = 0; i < queues; i++) {
+        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
 
-    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
-             chr->label);
+        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
+                 i, chr->label);
 
-    s = DO_UPCAST(VhostUserState, nc, nc);
+        s = DO_UPCAST(VhostUserState, nc, nc);
 
-    /* We don't provide a receive callback */
-    s->nc.receive_disabled = 1;
-    s->chr = chr;
-
-    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
+        /* We don't provide a receive callback */
+        s->nc.receive_disabled = 1;
+        s->chr = chr;
+        s->nc.queue_index = i;
 
+        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
+    }
     return 0;
 }
 
@@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
 int net_init_vhost_user(const NetClientOptions *opts, const char *name,
                         NetClientState *peer)
 {
+    uint32_t queues;
     const NetdevVhostUserOptions *vhost_user_opts;
     CharDriverState *chr;
 
@@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
         return -1;
     }
 
+    /* number of queues for multiqueue */
+    if (vhost_user_opts->has_queues) {
+        queues = vhost_user_opts->queues;
+    } else {
+        queues = 1;
+    }
 
-    return net_vhost_user_init(peer, "vhost_user", name, chr);
+    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
 }
diff --git a/qapi-schema.json b/qapi-schema.json
index f97ffa1..00791dd 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2444,12 +2444,16 @@
 #
 # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
 #
+# @queues: #optional number of queues to be created for multiqueue vhost-user
+#          (default: 1) (Since 2.4)
+#
 # Since 2.1
 ##
 { 'struct': 'NetdevVhostUserOptions',
   'data': {
     'chardev':        'str',
-    '*vhostforce':    'bool' } }
+    '*vhostforce':    'bool',
+    '*queues':        'uint32' } }
 
 ##
 # @NetClientOptions
diff --git a/qemu-options.hx b/qemu-options.hx
index ec356f6..dad035e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
 netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
 required hub automatically.
 
-@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
+@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
 
 Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
 be a unix domain socket backed one. The vhost-user uses a specifically defined
 protocol to pass vhost ioctl replacement messages to an application on the other
 end of the socket. On non-MSIX guests, the feature can be forced with
-@var{vhostforce}.
+@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
+be created for multiqueue vhost-user.
 
 Example:
 @example
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-05-28  1:23 [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Ouyang Changchun
@ 2015-07-08 14:29 ` Michael S. Tsirkin
  2015-07-08 22:00   ` Maxime Leroy
  2015-08-12  6:25 ` [Qemu-devel] [PATCH v6 0/2] vhost-user " Ouyang Changchun
  2015-08-30 15:28 ` [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Marcel Apfelbaum
  2 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-07-08 14:29 UTC (permalink / raw)
  To: Ouyang Changchun
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, n.nikolaev, luke,
	thomas.long, rkhan

On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
> Based on patch by Nikolay Nikolaev:
> Vhost-user will implement the multi queue support in a similar way
> to what vhost already has - a separate thread for each queue.
> To enable the multi queue functionality - a new command line parameter
> "queues" is introduced for the vhost-user netdev.
> 
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>

So testing turned up a significant issue with the protocol extension in this
one.  Specifically, remote has no idea how many queues guest actually
wants to use (it's dynamic, guest changes this at any time).
We need support for enabling and disabling queues dynamically.

Given we are past hard freeze, and given no one uses this yet
(dpdk upstream did not merge supporting protocol),
I think the best thing to do is to disable this functionality for 2.4.
I will send a patch to do this shortly.

I do think this support is important, so me and Marcel will try work on
it in the coming several weeks, and to come up with a better protocol.
I hope we'll be able to have a replacement ready by the time 2.4
is released and 2.5 development opens up so it can be merged first
thing.

It also seems that it will also align better with the plans to use this
in upstream dpdk.

-- 
MST

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-08 14:29 ` Michael S. Tsirkin
@ 2015-07-08 22:00   ` Maxime Leroy
  2015-07-09  1:29     ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
  2015-07-09  7:06     ` [Qemu-devel] " Michael S. Tsirkin
  0 siblings, 2 replies; 44+ messages in thread
From: Maxime Leroy @ 2015-07-08 22:00 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, rkhan, Ouyang Changchun

Hi Michael,

On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
>> Based on patch by Nikolay Nikolaev:
>> Vhost-user will implement the multi queue support in a similar way
>> to what vhost already has - a separate thread for each queue.
>> To enable the multi queue functionality - a new command line parameter
>> "queues" is introduced for the vhost-user netdev.
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>
> So testing turned up a significant issue with the protocol extension in this
> one.  Specifically, remote has no idea how many queues guest actually
> wants to use (it's dynamic, guest changes this at any time).
> We need support for enabling and disabling queues dynamically.
>
> Given we are past hard freeze, and given no one uses this yet
> (dpdk upstream did not merge supporting protocol),
> I think the best thing to do is to disable this functionality for 2.4.
> I will send a patch to do this shortly.

You are making a wrong statement, we already use multiqueue for
vhost-user and we expected to have this support officially integrated
in qemu 2.4.

Libvirt 1.2.17 has been released with multiqueue support for
vhost-user. (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
It checks against the version of qemu (i.e. 2.4)  to know if
multiqueue is supported or not by qemu.
(http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)

Dynamically enabling/disabling queue between host/guest is a nice
feature to have.
But it's not mandatory. You can still configure manually guest and
host to use the same number of queues.

I think this feature can be implemented later in qemu 2.5.

Regards,

Maxime

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v5] vhost-user: add multi queue support
  2015-07-08 22:00   ` Maxime Leroy
@ 2015-07-09  1:29     ` Ouyang, Changchun
  2015-07-09  7:31       ` Michael S. Tsirkin
  2015-07-09  7:06     ` [Qemu-devel] " Michael S. Tsirkin
  1 sibling, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-07-09  1:29 UTC (permalink / raw)
  To: snabb-devel, Michael S. Tsirkin
  Cc: Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev, Luke Gorrie,
	Long, Thomas, rkhan, Ouyang, Changchun



> -----Original Message-----
> From: snabb-devel@googlegroups.com [mailto:snabb-
> devel@googlegroups.com] On Behalf Of Maxime Leroy
> Sent: Thursday, July 9, 2015 6:01 AM
> To: Michael S. Tsirkin
> Cc: Ouyang, Changchun; snabb-devel@googlegroups.com; Marcel
> Apfelbaum; qemu-devel@nongnu.org; Nikolay Nikolaev; Luke Gorrie; Long,
> Thomas; rkhan@redhat.com
> Subject: [snabb-devel] Re: [Qemu-devel] [PATCH v5] vhost-user: add multi
> queue support
> 
> Hi Michael,
> 
> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
> >> Based on patch by Nikolay Nikolaev:
> >> Vhost-user will implement the multi queue support in a similar way to
> >> what vhost already has - a separate thread for each queue.
> >> To enable the multi queue functionality - a new command line
> >> parameter "queues" is introduced for the vhost-user netdev.
> >>
> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> >
> > So testing turned up a significant issue with the protocol extension
> > in this one.  Specifically, remote has no idea how many queues guest
> > actually wants to use (it's dynamic, guest changes this at any time).
> > We need support for enabling and disabling queues dynamically.

Do you mean we need control queue to negotiate the actual queue number between
Guest and host? Or something like that

> >
> > Given we are past hard freeze, and given no one uses this yet (dpdk
> > upstream did not merge supporting protocol), I think the best thing to
> > do is to disable this functionality for 2.4.
> > I will send a patch to do this shortly.
> 
> You are making a wrong statement, we already use multiqueue for vhost-
> user and we expected to have this support officially integrated in qemu 2.4.
> 
> Libvirt 1.2.17 has been released with multiqueue support for vhost-user.
> (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93
> fd18d1ba9eacd6)
> It checks against the version of qemu (i.e. 2.4)  to know if multiqueue is
> supported or not by qemu.
> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a
> 3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
> 
> Dynamically enabling/disabling queue between host/guest is a nice feature
> to have.
> But it's not mandatory. You can still configure manually guest and host to use
> the same number of queues.

Same number of queues on host and guest can work normally, I have validated it with dpdk.

> 

Maybe we could consider still having this in 2.4,
And have an enhancement patch set to implement dynamically enabling/disabling in 2.5 or 2.4.x
After extending the vhost-user spec. 

Thanks
Changchun


^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-08 22:00   ` Maxime Leroy
  2015-07-09  1:29     ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
@ 2015-07-09  7:06     ` Michael S. Tsirkin
  2015-07-09 12:00       ` Martin Kletzander
  1 sibling, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-07-09  7:06 UTC (permalink / raw)
  To: Maxime Leroy
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, rkhan, Martin Kletzander,
	Ouyang Changchun

On Thu, Jul 09, 2015 at 12:00:59AM +0200, Maxime Leroy wrote:
> Hi Michael,
> 
> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
> >> Based on patch by Nikolay Nikolaev:
> >> Vhost-user will implement the multi queue support in a similar way
> >> to what vhost already has - a separate thread for each queue.
> >> To enable the multi queue functionality - a new command line parameter
> >> "queues" is introduced for the vhost-user netdev.
> >>
> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> >
> > So testing turned up a significant issue with the protocol extension in this
> > one.  Specifically, remote has no idea how many queues guest actually
> > wants to use (it's dynamic, guest changes this at any time).
> > We need support for enabling and disabling queues dynamically.
> >
> > Given we are past hard freeze, and given no one uses this yet
> > (dpdk upstream did not merge supporting protocol),
> > I think the best thing to do is to disable this functionality for 2.4.
> > I will send a patch to do this shortly.
> 
> You are making a wrong statement, we already use multiqueue for
> vhost-user and we expected to have this support officially integrated
> in qemu 2.4.
> 
> Libvirt 1.2.17 has been released with multiqueue support for
> vhost-user. (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
> It checks against the version of qemu (i.e. 2.4)  to know if
> multiqueue is supported or not by qemu.
> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)

Ouch. Just another example showing how version checks are evil.
We don't want to break libvirt, I agree.

I think what we can do is accept the command line created
by libvirt, just ignore it and use a single queue only.

> Dynamically enabling/disabling queue between host/guest is a nice
> feature to have.
> But it's not mandatory.

It's mandated by the virtio spec.

> You can still configure manually guest and
> host to use the same number of queues.
> 
> I think this feature can be implemented later in qemu 2.5.
> 
> Regards,
> 
> Maxime

Sorry, that's not how virtio is supposed to work. It must downgrade
gracefully, not just stop working or crash guest.

-- 
MST

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v5] vhost-user: add multi queue support
  2015-07-09  1:29     ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
@ 2015-07-09  7:31       ` Michael S. Tsirkin
  0 siblings, 0 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-07-09  7:31 UTC (permalink / raw)
  To: Ouyang, Changchun
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, Long, Thomas, rkhan

On Thu, Jul 09, 2015 at 01:29:48AM +0000, Ouyang, Changchun wrote:
> 
> 
> > -----Original Message-----
> > From: snabb-devel@googlegroups.com [mailto:snabb-
> > devel@googlegroups.com] On Behalf Of Maxime Leroy
> > Sent: Thursday, July 9, 2015 6:01 AM
> > To: Michael S. Tsirkin
> > Cc: Ouyang, Changchun; snabb-devel@googlegroups.com; Marcel
> > Apfelbaum; qemu-devel@nongnu.org; Nikolay Nikolaev; Luke Gorrie; Long,
> > Thomas; rkhan@redhat.com
> > Subject: [snabb-devel] Re: [Qemu-devel] [PATCH v5] vhost-user: add multi
> > queue support
> > 
> > Hi Michael,
> > 
> > On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
> > >> Based on patch by Nikolay Nikolaev:
> > >> Vhost-user will implement the multi queue support in a similar way to
> > >> what vhost already has - a separate thread for each queue.
> > >> To enable the multi queue functionality - a new command line
> > >> parameter "queues" is introduced for the vhost-user netdev.
> > >>
> > >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > >
> > > So testing turned up a significant issue with the protocol extension
> > > in this one.  Specifically, remote has no idea how many queues guest
> > > actually wants to use (it's dynamic, guest changes this at any time).
> > > We need support for enabling and disabling queues dynamically.
> 
> Do you mean we need control queue to negotiate the actual queue number between
> Guest and host? Or something like that

Exactly. In fact vhost user currently gets CTRL_VQ feature flag
which it really shouldn't since dpdk does not handle the
control VQ.

> > >
> > > Given we are past hard freeze, and given no one uses this yet (dpdk
> > > upstream did not merge supporting protocol), I think the best thing to
> > > do is to disable this functionality for 2.4.
> > > I will send a patch to do this shortly.
> > 
> > You are making a wrong statement, we already use multiqueue for vhost-
> > user and we expected to have this support officially integrated in qemu 2.4.
> > 
> > Libvirt 1.2.17 has been released with multiqueue support for vhost-user.
> > (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93
> > fd18d1ba9eacd6)
> > It checks against the version of qemu (i.e. 2.4)  to know if multiqueue is
> > supported or not by qemu.
> > (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a
> > 3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
> > 
> > Dynamically enabling/disabling queue between host/guest is a nice feature
> > to have.
> > But it's not mandatory. You can still configure manually guest and host to use
> > the same number of queues.
> 
> Same number of queues on host and guest can work normally, I have validated it with dpdk.

Try to use upstream dpdk without your patches and upstream qemu (with
patches integrated) and you will see some of the issues I am
talking about: crashes in guest and in dpdk.


> > 
> 
> Maybe we could consider still having this in 2.4,

I think that would be a mistake simply because it affects the
guest/host interface.

I think spec compliance is extremely important. Otherwise guest driver
writers need to study individual implementation bugs and work around
them, and that's just too painful.

virtio spec requires the number of queues to be configurable on the fly,
assuming we can't do that at the moment (and to me, it looks like
there is no way to give the necessary info to dpdk)
we simply must not set the multiqueue capability.

Two main things are broken on the QEMU side:
- MQ feature requires CTRL vq. QEMU does not pass CTRL vq info to DPDK
  so of course it just lies to guest that it's supported:
  all info is buffered in QEMU but stays unused.

- MQ feature requires that max number of queues is reported
  to guest. QEMU does not request this info from DPDK so
  of course it has no way to know this number.
  Instead it just assumes DPDK can handle whatever's thrown at it,
  but naturally this can't work in practice so of course it doesn't.

> And have an enhancement patch set to implement dynamically enabling/disabling in 2.5 or 2.4.x
> After extending the vhost-user spec. 
> 
> Thanks
> Changchun

2.5 development is just around the corner. With enough effort we can
have the patches upstream first thing in 2.5 cycle.

Once there, the whole feature can be backported if enough people
are prepared to dedicate resources to maintaining 2.4.x.
To me this sounds like a much better deal for everyone
than releasing a known-broken device and trying to fix it up.

-- 
MST

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-09  7:06     ` [Qemu-devel] " Michael S. Tsirkin
@ 2015-07-09 12:00       ` Martin Kletzander
  2015-07-09 12:24         ` Maxime Leroy
  0 siblings, 1 reply; 44+ messages in thread
From: Martin Kletzander @ 2015-07-09 12:00 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, Maxime Leroy, rkhan, Ouyang Changchun

[-- Attachment #1: Type: text/plain, Size: 2979 bytes --]

On Thu, Jul 09, 2015 at 10:06:35AM +0300, Michael S. Tsirkin wrote:
>On Thu, Jul 09, 2015 at 12:00:59AM +0200, Maxime Leroy wrote:
>> Hi Michael,
>>
>> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
>> >> Based on patch by Nikolay Nikolaev:
>> >> Vhost-user will implement the multi queue support in a similar way
>> >> to what vhost already has - a separate thread for each queue.
>> >> To enable the multi queue functionality - a new command line parameter
>> >> "queues" is introduced for the vhost-user netdev.
>> >>
>> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>> >
>> > So testing turned up a significant issue with the protocol extension in this
>> > one.  Specifically, remote has no idea how many queues guest actually
>> > wants to use (it's dynamic, guest changes this at any time).
>> > We need support for enabling and disabling queues dynamically.
>> >
>> > Given we are past hard freeze, and given no one uses this yet
>> > (dpdk upstream did not merge supporting protocol),
>> > I think the best thing to do is to disable this functionality for 2.4.
>> > I will send a patch to do this shortly.
>>
>> You are making a wrong statement, we already use multiqueue for
>> vhost-user and we expected to have this support officially integrated
>> in qemu 2.4.
>>
>> Libvirt 1.2.17 has been released with multiqueue support for
>> vhost-user. (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
>> It checks against the version of qemu (i.e. 2.4)  to know if
>> multiqueue is supported or not by qemu.
>> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
>
>Ouch. Just another example showing how version checks are evil.
>We don't want to break libvirt, I agree.
>

Yes, exactly.  Unfortunately if QEMU doesn't expose it in any way we
don't have many more options.

>I think what we can do is accept the command line created
>by libvirt, just ignore it and use a single queue only.
>

Anyway, I think it would be pretty OK to disable it *if and only if*
you error out with a sensible error message (e.g. "multiple queues are
not supported yet").

And from 2.5 and next libvirt release we can fix this properly
(QEMU - exposing the capability and libvirt - checking for it).

>> Dynamically enabling/disabling queue between host/guest is a nice
>> feature to have.
>> But it's not mandatory.
>
>It's mandated by the virtio spec.
>
>> You can still configure manually guest and
>> host to use the same number of queues.
>>
>> I think this feature can be implemented later in qemu 2.5.
>>
>> Regards,
>>
>> Maxime
>
>Sorry, that's not how virtio is supposed to work. It must downgrade
>gracefully, not just stop working or crash guest.
>
>--
>MST

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-09 12:00       ` Martin Kletzander
@ 2015-07-09 12:24         ` Maxime Leroy
  2015-07-09 12:33           ` Martin Kletzander
  2015-07-09 12:54           ` Michael S. Tsirkin
  0 siblings, 2 replies; 44+ messages in thread
From: Maxime Leroy @ 2015-07-09 12:24 UTC (permalink / raw)
  To: Martin Kletzander, Michael S. Tsirkin
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, rkhan, Ouyang Changchun

Hi Martin, Michael,

On Thu, Jul 9, 2015 at 2:00 PM, Martin Kletzander <mkletzan@redhat.com> wrote:
> On Thu, Jul 09, 2015 at 10:06:35AM +0300, Michael S. Tsirkin wrote:
>>
>> On Thu, Jul 09, 2015 at 12:00:59AM +0200, Maxime Leroy wrote:
>>>
>>> Hi Michael,
>>>
>>> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com>
>>> wrote:
>>> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
>>> >> Based on patch by Nikolay Nikolaev:
>>> >> Vhost-user will implement the multi queue support in a similar way
>>> >> to what vhost already has - a separate thread for each queue.
>>> >> To enable the multi queue functionality - a new command line parameter
>>> >> "queues" is introduced for the vhost-user netdev.
>>> >>
>>> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>>> >
>>> > So testing turned up a significant issue with the protocol extension in
>>> > this
>>> > one.  Specifically, remote has no idea how many queues guest actually
>>> > wants to use (it's dynamic, guest changes this at any time).
>>> > We need support for enabling and disabling queues dynamically.
>>> >
>>> > Given we are past hard freeze, and given no one uses this yet
>>> > (dpdk upstream did not merge supporting protocol),
>>> > I think the best thing to do is to disable this functionality for 2.4.
>>> > I will send a patch to do this shortly.
>>>
>>> You are making a wrong statement, we already use multiqueue for
>>> vhost-user and we expected to have this support officially integrated
>>> in qemu 2.4.
>>>
>>> Libvirt 1.2.17 has been released with multiqueue support for
>>> vhost-user.
>>> (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
>>> It checks against the version of qemu (i.e. 2.4)  to know if
>>> multiqueue is supported or not by qemu.
>>>
>>> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
>>
>>
>> Ouch. Just another example showing how version checks are evil.
>> We don't want to break libvirt, I agree.
>>
>
> Yes, exactly.  Unfortunately if QEMU doesn't expose it in any way we
> don't have many more options.
>
>> I think what we can do is accept the command line created
>> by libvirt, just ignore it and use a single queue only.
>>
>
> Anyway, I think it would be pretty OK to disable it *if and only if*
> you error out with a sensible error message (e.g. "multiple queues are
> not supported yet").

I consider that accepting the queue parameter for vhost-user but only
creates a single queue is a bug.
Unfortunately I don't think we have many solution here for libvirt 1.2.17.0

Agree with Martin, at least, we should display an error message.

>
> And from 2.5 and next libvirt release we can fix this properly
> (QEMU - exposing the capability and libvirt - checking for it).

is it possible to backport this fix in the branch 1.2.17 of libvirt ?

>
>
>>> Dynamically enabling/disabling queue between host/guest is a nice
>>> feature to have.
>>> But it's not mandatory.
>>
>> Same number of queues on host and guest can work normally, I have validated it with dpdk.
>
> Try to use upstream dpdk without your patches and upstream qemu (with
> patches integrated) and you will see some of the issues I am
> talking about: crashes in guest and in dpdk.

I test with my own vhost-user implementation, and didn't observe any
crashes on host or guest.
Traffic was just not process by the guess, when the guess was
configured with less ring that the host.

Anyway, I have to do some modification in my vhost-user implementation
because the vhost-user protocol has changed.

The VHOST_USER_RESET_OWNER payload has changed in this patch. Now we
are setting the vq_index.

But the documentation has not been updated:
http://git.qemu.org/?p=qemu.git;a=blob;f=docs/specs/vhost-user.txt;h=2c8e9347ccee80d11b5e740b717093c1e536af02;hb=HEAD#l165

I am wondering if the VHOST_USER_VERSION should have been increased
with this patch ?

>> >
>>
[..]
>
> Two main things are broken on the QEMU side:
> - MQ feature requires CTRL vq. QEMU does not pass CTRL vq info to DPDK
>   so of course it just lies to guest that it's supported:
>   all info is buffered in QEMU but stays unused.
>
> - MQ feature requires that max number of queues is reported
>   to guest. QEMU does not request this info from DPDK so
>   of course it has no way to know this number.
>   Instead it just assumes DPDK can handle whatever's thrown at it,
>   but naturally this can't work in practice so of course it doesn't.

For my understanding, vhost-user just translates ioctl for
/dev/vhost-net into vhost user request over a socket.

Activation/deactivation of queues for virtio-net, it's not done with
ioctl on /dev/vhost-net.
But by detach or attach tun queues to virtio ring with ioctl
TUNSETQUEUE with flags IFF_ATTACH/DETACH_QUEUE to /dev/net/tun.

So, how do you plan to extend vhost-user protocol to notify
activation/deactivation of queue ?

>
>> And have an enhancement patch set to implement dynamically enabling/disabling in 2.5 or 2.4.x
>> After extending the vhost-user spec.
>>
>> Thanks
>> Changchun
>
> 2.5 development is just around the corner. With enough effort we can
> have the patches upstream first thing in 2.5 cycle.

I'll be happy to help you testing your new patches for multiqueue
support against my vhost-user implementation.
Could you please add me in CC when you send these patches on the mailing list ?

>
> Once there, the whole feature can be backported if enough people
> are prepared to dedicate resources to maintaining 2.4.x.
> To me this sounds like a much better deal for everyone
> than releasing a known-broken device and trying to fix it up.
>

It would be really nice to backport this feature in qemu 2.4.x.
When will it be available into a 2.4.x maintenance?

Regards,

Maxime

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-09 12:24         ` Maxime Leroy
@ 2015-07-09 12:33           ` Martin Kletzander
  2015-07-09 12:54           ` Michael S. Tsirkin
  1 sibling, 0 replies; 44+ messages in thread
From: Martin Kletzander @ 2015-07-09 12:33 UTC (permalink / raw)
  To: Maxime Leroy
  Cc: snabb-devel, Marcel Apfelbaum, Michael S. Tsirkin, qemu-devel,
	Nikolay Nikolaev, Luke Gorrie, thomas.long, rkhan,
	Ouyang Changchun

[-- Attachment #1: Type: text/plain, Size: 3211 bytes --]

On Thu, Jul 09, 2015 at 02:24:51PM +0200, Maxime Leroy wrote:
>Hi Martin, Michael,
>
>On Thu, Jul 9, 2015 at 2:00 PM, Martin Kletzander <mkletzan@redhat.com> wrote:
>> On Thu, Jul 09, 2015 at 10:06:35AM +0300, Michael S. Tsirkin wrote:
>>>
>>> On Thu, Jul 09, 2015 at 12:00:59AM +0200, Maxime Leroy wrote:
>>>>
>>>> Hi Michael,
>>>>
>>>> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com>
>>>> wrote:
>>>> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
>>>> >> Based on patch by Nikolay Nikolaev:
>>>> >> Vhost-user will implement the multi queue support in a similar way
>>>> >> to what vhost already has - a separate thread for each queue.
>>>> >> To enable the multi queue functionality - a new command line parameter
>>>> >> "queues" is introduced for the vhost-user netdev.
>>>> >>
>>>> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>>> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>>>> >
>>>> > So testing turned up a significant issue with the protocol extension in
>>>> > this
>>>> > one.  Specifically, remote has no idea how many queues guest actually
>>>> > wants to use (it's dynamic, guest changes this at any time).
>>>> > We need support for enabling and disabling queues dynamically.
>>>> >
>>>> > Given we are past hard freeze, and given no one uses this yet
>>>> > (dpdk upstream did not merge supporting protocol),
>>>> > I think the best thing to do is to disable this functionality for 2.4.
>>>> > I will send a patch to do this shortly.
>>>>
>>>> You are making a wrong statement, we already use multiqueue for
>>>> vhost-user and we expected to have this support officially integrated
>>>> in qemu 2.4.
>>>>
>>>> Libvirt 1.2.17 has been released with multiqueue support for
>>>> vhost-user.
>>>> (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
>>>> It checks against the version of qemu (i.e. 2.4)  to know if
>>>> multiqueue is supported or not by qemu.
>>>>
>>>> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
>>>
>>>
>>> Ouch. Just another example showing how version checks are evil.
>>> We don't want to break libvirt, I agree.
>>>
>>
>> Yes, exactly.  Unfortunately if QEMU doesn't expose it in any way we
>> don't have many more options.
>>
>>> I think what we can do is accept the command line created
>>> by libvirt, just ignore it and use a single queue only.
>>>
>>
>> Anyway, I think it would be pretty OK to disable it *if and only if*
>> you error out with a sensible error message (e.g. "multiple queues are
>> not supported yet").
>
>I consider that accepting the queue parameter for vhost-user but only
>creates a single queue is a bug.
>Unfortunately I don't think we have many solution here for libvirt 1.2.17.0
>
>Agree with Martin, at least, we should display an error message.
>
>>
>> And from 2.5 and next libvirt release we can fix this properly
>> (QEMU - exposing the capability and libvirt - checking for it).
>
>is it possible to backport this fix in the branch 1.2.17 of libvirt ?
>

Yes, sure, that's what maintenance branches are for ;)

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-07-09 12:24         ` Maxime Leroy
  2015-07-09 12:33           ` Martin Kletzander
@ 2015-07-09 12:54           ` Michael S. Tsirkin
  1 sibling, 0 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-07-09 12:54 UTC (permalink / raw)
  To: Maxime Leroy
  Cc: snabb-devel, Marcel Apfelbaum, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, rkhan, Martin Kletzander,
	Ouyang Changchun

On Thu, Jul 09, 2015 at 02:24:51PM +0200, Maxime Leroy wrote:
> Hi Martin, Michael,
> 
> On Thu, Jul 9, 2015 at 2:00 PM, Martin Kletzander <mkletzan@redhat.com> wrote:
> > On Thu, Jul 09, 2015 at 10:06:35AM +0300, Michael S. Tsirkin wrote:
> >>
> >> On Thu, Jul 09, 2015 at 12:00:59AM +0200, Maxime Leroy wrote:
> >>>
> >>> Hi Michael,
> >>>
> >>> On Wed, Jul 8, 2015 at 4:29 PM, Michael S. Tsirkin <mst@redhat.com>
> >>> wrote:
> >>> > On Thu, May 28, 2015 at 09:23:06AM +0800, Ouyang Changchun wrote:
> >>> >> Based on patch by Nikolay Nikolaev:
> >>> >> Vhost-user will implement the multi queue support in a similar way
> >>> >> to what vhost already has - a separate thread for each queue.
> >>> >> To enable the multi queue functionality - a new command line parameter
> >>> >> "queues" is introduced for the vhost-user netdev.
> >>> >>
> >>> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >>> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> >>> >
> >>> > So testing turned up a significant issue with the protocol extension in
> >>> > this
> >>> > one.  Specifically, remote has no idea how many queues guest actually
> >>> > wants to use (it's dynamic, guest changes this at any time).
> >>> > We need support for enabling and disabling queues dynamically.
> >>> >
> >>> > Given we are past hard freeze, and given no one uses this yet
> >>> > (dpdk upstream did not merge supporting protocol),
> >>> > I think the best thing to do is to disable this functionality for 2.4.
> >>> > I will send a patch to do this shortly.
> >>>
> >>> You are making a wrong statement, we already use multiqueue for
> >>> vhost-user and we expected to have this support officially integrated
> >>> in qemu 2.4.
> >>>
> >>> Libvirt 1.2.17 has been released with multiqueue support for
> >>> vhost-user.
> >>> (http://libvirt.org/git/?p=libvirt.git;a=commit;h=366c22f2bcf1ddb8253c123f93fd18d1ba9eacd6)
> >>> It checks against the version of qemu (i.e. 2.4)  to know if
> >>> multiqueue is supported or not by qemu.
> >>>
> >>> (http://libvirt.org/git/?p=libvirt.git;a=commitdiff;h=7971723b985b9adc27122a3503e7ab38ced2b57f;hp=e7f5510ef2d28ca0ae0ed5751b1fd3018130d6c1)
> >>
> >>
> >> Ouch. Just another example showing how version checks are evil.
> >> We don't want to break libvirt, I agree.
> >>
> >
> > Yes, exactly.  Unfortunately if QEMU doesn't expose it in any way we
> > don't have many more options.
> >
> >> I think what we can do is accept the command line created
> >> by libvirt, just ignore it and use a single queue only.
> >>
> >
> > Anyway, I think it would be pretty OK to disable it *if and only if*
> > you error out with a sensible error message (e.g. "multiple queues are
> > not supported yet").
> 
> I consider that accepting the queue parameter for vhost-user but only
> creates a single queue is a bug.
> Unfortunately I don't think we have many solution here for libvirt 1.2.17.0
> 
> Agree with Martin, at least, we should display an error message.
> 
> >
> > And from 2.5 and next libvirt release we can fix this properly
> > (QEMU - exposing the capability and libvirt - checking for it).
> 
> is it possible to backport this fix in the branch 1.2.17 of libvirt ?
> 
> >
> >
> >>> Dynamically enabling/disabling queue between host/guest is a nice
> >>> feature to have.
> >>> But it's not mandatory.
> >>
> >> Same number of queues on host and guest can work normally, I have validated it with dpdk.
> >
> > Try to use upstream dpdk without your patches and upstream qemu (with
> > patches integrated) and you will see some of the issues I am
> > talking about: crashes in guest and in dpdk.
> 
> I test with my own vhost-user implementation, and didn't observe any
> crashes on host or guest.
> Traffic was just not process by the guess, when the guess was
> configured with less ring that the host.
> 
> Anyway, I have to do some modification in my vhost-user implementation
> because the vhost-user protocol has changed.
> 
> The VHOST_USER_RESET_OWNER payload has changed in this patch. Now we
> are setting the vq_index.

As I explained I plan to revert this anyway.

> 
> But the documentation has not been updated:
> http://git.qemu.org/?p=qemu.git;a=blob;f=docs/specs/vhost-user.txt;h=2c8e9347ccee80d11b5e740b717093c1e536af02;hb=HEAD#l165
> I am wondering if the VHOST_USER_VERSION should have been increased
> with this patch ?

Unfortunately everyone seems to ignore the version.
I think using feature bits works though.


> >> >
> >>
> [..]
> >
> > Two main things are broken on the QEMU side:
> > - MQ feature requires CTRL vq. QEMU does not pass CTRL vq info to DPDK
> >   so of course it just lies to guest that it's supported:
> >   all info is buffered in QEMU but stays unused.
> >
> > - MQ feature requires that max number of queues is reported
> >   to guest. QEMU does not request this info from DPDK so
> >   of course it has no way to know this number.
> >   Instead it just assumes DPDK can handle whatever's thrown at it,
> >   but naturally this can't work in practice so of course it doesn't.
> 
> For my understanding, vhost-user just translates ioctl for
> /dev/vhost-net into vhost user request over a socket.
> 
> Activation/deactivation of queues for virtio-net, it's not done with
> ioctl on /dev/vhost-net.
> But by detach or attach tun queues to virtio ring with ioctl
> TUNSETQUEUE with flags IFF_ATTACH/DETACH_QUEUE to /dev/net/tun.
> 
> So, how do you plan to extend vhost-user protocol to notify
> activation/deactivation of queue ?
> 
> >
> >> And have an enhancement patch set to implement dynamically enabling/disabling in 2.5 or 2.4.x
> >> After extending the vhost-user spec.
> >>
> >> Thanks
> >> Changchun
> >
> > 2.5 development is just around the corner. With enough effort we can
> > have the patches upstream first thing in 2.5 cycle.
> 
> I'll be happy to help you testing your new patches for multiqueue
> support against my vhost-user implementation.
> Could you please add me in CC when you send these patches on the mailing list ?
> 
> >
> > Once there, the whole feature can be backported if enough people
> > are prepared to dedicate resources to maintaining 2.4.x.
> > To me this sounds like a much better deal for everyone
> > than releasing a known-broken device and trying to fix it up.
> >
> 
> It would be really nice to backport this feature in qemu 2.4.x.
> When will it be available into a 2.4.x maintenance?
> 
> Regards,
> 
> Maxime

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH v6 0/2] vhost-user multi queue support
  2015-05-28  1:23 [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Ouyang Changchun
  2015-07-08 14:29 ` Michael S. Tsirkin
@ 2015-08-12  6:25 ` Ouyang Changchun
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 1/2] vhost-user: add " Ouyang Changchun
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue Ouyang Changchun
  2015-08-30 15:28 ` [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Marcel Apfelbaum
  2 siblings, 2 replies; 44+ messages in thread
From: Ouyang Changchun @ 2015-08-12  6:25 UTC (permalink / raw)
  To: qemu-devel, mst
  Cc: snabb-devel, thibaut.collet, n.nikolaev, luke, thomas.long,
	changchun.ouyang

Vhost-user will implement the multi queue support in a similar way
to what vhost already has - a separate thread for each queue.
To enable the multi queue functionality - a new command line parameter
"queues" is introduced for the vhost-user netdev.

Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
actual virt queue, which is similar to attach/detach queue for tap device.
virtio driver on guest doesn't have to use max virt queue pair, it could
enable any number of virt queue ranging from 1 to max virt queue pair.
 
It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.

Any comment is welcome for the patch set.

It has dependency on a few other patch(set):
"vhost-user: protocol updates" series
proposed earlier by Michael S. Tsirkin

RESET_OWNER change is based on commit:
294ce717e0f212ed0763307f3eab72b4a1bdf4d0  

Changchun Ouyang (2):
  vhost-user: add multi queue support
  vhost-user: new protocol feature for multi queue

 docs/specs/vhost-user.txt         | 24 +++++++++++++++++++-
 hw/net/vhost_net.c                | 21 +++++++++++++++++-
 hw/net/virtio-net.c               |  2 ++
 hw/virtio/vhost-user.c            | 46 ++++++++++++++++++++++++++++++++++++---
 include/hw/virtio/vhost-backend.h |  2 ++
 include/net/vhost_net.h           |  1 +
 net/vhost-user.c                  | 37 ++++++++++++++++++++-----------
 qapi-schema.json                  |  6 ++++-
 qemu-options.hx                   |  5 +++--
 9 files changed, 123 insertions(+), 21 deletions(-)

-- 
1.8.4.2

^ permalink raw reply	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-12  6:25 ` [Qemu-devel] [PATCH v6 0/2] vhost-user " Ouyang Changchun
@ 2015-08-12  6:25   ` Ouyang Changchun
  2015-08-13  9:18     ` Michael S. Tsirkin
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue Ouyang Changchun
  1 sibling, 1 reply; 44+ messages in thread
From: Ouyang Changchun @ 2015-08-12  6:25 UTC (permalink / raw)
  To: qemu-devel, mst
  Cc: snabb-devel, thibaut.collet, n.nikolaev, luke, thomas.long,
	changchun.ouyang

Based on patch by Nikolay Nikolaev:
Vhost-user will implement the multi queue support in a similar way
to what vhost already has - a separate thread for each queue.
To enable the multi queue functionality - a new command line parameter
"queues" is introduced for the vhost-user netdev.

The RESET_OWNER change is based on commit:
   294ce717e0f212ed0763307f3eab72b4a1bdf4d0
If it is reverted, the patch need update for it accordingly.

Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
---
Changes since v5:
 - fix the message descption for VHOST_RESET_OWNER in vhost-user txt

Changes since v4:
 - remove the unnecessary trailing '\n'

Changes since v3:
 - fix one typo and wrap one long line

Changes since v2:
 - fix vq index issue for set_vring_call
   When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
   thus it could be a random value. The random value leads to crash in vhost after passing down
   to vhost, as vhost use this random value to index an array index.
 - fix the typo in the doc and description
 - address vq index for reset_owner

Changes since v1:
 - use s->nc.info_str when bringing up/down the backend

 docs/specs/vhost-user.txt |  7 ++++++-
 hw/net/vhost_net.c        |  3 ++-
 hw/virtio/vhost-user.c    | 11 ++++++++++-
 net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
 qapi-schema.json          |  6 +++++-
 qemu-options.hx           |  5 +++--
 6 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
index 70da3b1..9390f89 100644
--- a/docs/specs/vhost-user.txt
+++ b/docs/specs/vhost-user.txt
@@ -135,6 +135,11 @@ As older slaves don't support negotiating protocol features,
 a feature bit was dedicated for this purpose:
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
+Multi queue support
+-------------------
+The protocol supports multiple queues by setting all index fields in the sent
+messages to a properly calculated value.
+
 Message types
 -------------
 
@@ -198,7 +203,7 @@ Message types
 
       Id: 4
       Equivalent ioctl: VHOST_RESET_OWNER
-      Master payload: N/A
+      Master payload: vring state description
 
       Issued when a new connection is about to be closed. The Master will no
       longer own this connection (and will usually close it).
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 1f25cb3..9cd6c05 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -159,6 +159,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
 
     net->dev.nvqs = 2;
     net->dev.vqs = net->vqs;
+    net->dev.vq_index = net->nc->queue_index;
 
     r = vhost_dev_init(&net->dev, options->opaque,
                        options->backend_type, options->force);
@@ -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
         for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
             const VhostOps *vhost_ops = net->dev.vhost_ops;
             int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
-                                          NULL);
+                                          &file);
             assert(r >= 0);
         }
     }
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 27ba035..fb11d4c 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
         break;
 
     case VHOST_USER_SET_OWNER:
+        break;
+
     case VHOST_USER_RESET_OWNER:
+        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
+        msg.size = sizeof(m.state);
         break;
 
     case VHOST_USER_SET_MEM_TABLE:
@@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
     case VHOST_USER_SET_VRING_NUM:
     case VHOST_USER_SET_VRING_BASE:
         memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
         msg.size = sizeof(m.state);
         break;
 
     case VHOST_USER_GET_VRING_BASE:
         memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
+        msg.state.index += dev->vq_index;
         msg.size = sizeof(m.state);
         need_reply = 1;
         break;
 
     case VHOST_USER_SET_VRING_ADDR:
         memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
+        msg.addr.index += dev->vq_index;
         msg.size = sizeof(m.addr);
         break;
 
@@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
     case VHOST_USER_SET_VRING_CALL:
     case VHOST_USER_SET_VRING_ERR:
         file = arg;
-        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
+        msg.u64 = (file->index + dev->vq_index) & VHOST_USER_VRING_IDX_MASK;
         msg.size = sizeof(m.u64);
         if (ioeventfd_enabled() && file->fd > 0) {
             fds[fd_num++] = file->fd;
@@ -322,6 +330,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
                 error_report("Received bad msg size.");
                 return -1;
             }
+            msg.state.index -= dev->vq_index;
             memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
             break;
         default:
diff --git a/net/vhost-user.c b/net/vhost-user.c
index 1d86a2b..904d8af 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque, int event)
     case CHR_EVENT_OPENED:
         vhost_user_start(s);
         net_vhost_link_down(s, false);
-        error_report("chardev \"%s\" went up", s->chr->label);
+        error_report("chardev \"%s\" went up", s->nc.info_str);
         break;
     case CHR_EVENT_CLOSED:
         net_vhost_link_down(s, true);
         vhost_user_stop(s);
-        error_report("chardev \"%s\" went down", s->chr->label);
+        error_report("chardev \"%s\" went down", s->nc.info_str);
         break;
     }
 }
 
 static int net_vhost_user_init(NetClientState *peer, const char *device,
-                               const char *name, CharDriverState *chr)
+                               const char *name, CharDriverState *chr,
+                               uint32_t queues)
 {
     NetClientState *nc;
     VhostUserState *s;
+    int i;
 
-    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
+    for (i = 0; i < queues; i++) {
+        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
 
-    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
-             chr->label);
+        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
+                 i, chr->label);
 
-    s = DO_UPCAST(VhostUserState, nc, nc);
+        s = DO_UPCAST(VhostUserState, nc, nc);
 
-    /* We don't provide a receive callback */
-    s->nc.receive_disabled = 1;
-    s->chr = chr;
-
-    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
+        /* We don't provide a receive callback */
+        s->nc.receive_disabled = 1;
+        s->chr = chr;
+        s->nc.queue_index = i;
 
+        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
+    }
     return 0;
 }
 
@@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
 int net_init_vhost_user(const NetClientOptions *opts, const char *name,
                         NetClientState *peer)
 {
+    uint32_t queues;
     const NetdevVhostUserOptions *vhost_user_opts;
     CharDriverState *chr;
 
@@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
         return -1;
     }
 
+    /* number of queues for multiqueue */
+    if (vhost_user_opts->has_queues) {
+        queues = vhost_user_opts->queues;
+    } else {
+        queues = 1;
+    }
 
-    return net_vhost_user_init(peer, "vhost_user", name, chr);
+    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
 }
diff --git a/qapi-schema.json b/qapi-schema.json
index f97ffa1..51e40ce 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2444,12 +2444,16 @@
 #
 # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
 #
+# @queues: #optional number of queues to be created for multiqueue vhost-user
+#          (default: 1) (Since 2.5)
+#
 # Since 2.1
 ##
 { 'struct': 'NetdevVhostUserOptions',
   'data': {
     'chardev':        'str',
-    '*vhostforce':    'bool' } }
+    '*vhostforce':    'bool',
+    '*queues':        'uint32' } }
 
 ##
 # @NetClientOptions
diff --git a/qemu-options.hx b/qemu-options.hx
index ec356f6..dad035e 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
 netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
 required hub automatically.
 
-@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
+@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
 
 Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
 be a unix domain socket backed one. The vhost-user uses a specifically defined
 protocol to pass vhost ioctl replacement messages to an application on the other
 end of the socket. On non-MSIX guests, the feature can be forced with
-@var{vhostforce}.
+@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
+be created for multiqueue vhost-user.
 
 Example:
 @example
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-08-12  6:25 ` [Qemu-devel] [PATCH v6 0/2] vhost-user " Ouyang Changchun
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 1/2] vhost-user: add " Ouyang Changchun
@ 2015-08-12  6:25   ` Ouyang Changchun
  2015-08-13  9:22     ` Michael S. Tsirkin
  1 sibling, 1 reply; 44+ messages in thread
From: Ouyang Changchun @ 2015-08-12  6:25 UTC (permalink / raw)
  To: qemu-devel, mst
  Cc: snabb-devel, thibaut.collet, n.nikolaev, luke, thomas.long,
	changchun.ouyang

This patch is based on top of "vhost-user: protocol updates" series
proposed earlier by Michael S. Tsirkin.

Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
actual virt queue, which is similar to attach/detach queue for tap device.
virtio driver on guest doesn't have to use max virt queue pair, it could
enable any number of virt queue ranging from 1 to max virt queue pair.

It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.

Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
---
This is added since v5

 docs/specs/vhost-user.txt         | 17 +++++++++++++++++
 hw/net/vhost_net.c                | 18 ++++++++++++++++++
 hw/net/virtio-net.c               |  2 ++
 hw/virtio/vhost-user.c            | 35 +++++++++++++++++++++++++++++++++--
 include/hw/virtio/vhost-backend.h |  2 ++
 include/net/vhost_net.h           |  1 +
 6 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
index 9390f89..cca3e5b 100644
--- a/docs/specs/vhost-user.txt
+++ b/docs/specs/vhost-user.txt
@@ -135,6 +135,10 @@ As older slaves don't support negotiating protocol features,
 a feature bit was dedicated for this purpose:
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
 
+The Slave uses vring flag to notify the vhost-user whether one virtq is enabled
+or not. This request doesn't require replies:
+#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
+
 Multi queue support
 -------------------
 The protocol supports multiple queues by setting all index fields in the sent
@@ -306,3 +310,16 @@ Message types
       Bits (0-7) of the payload contain the vring index. Bit 8 is the
       invalid FD flag. This flag is set when there is no file descriptor
       in the ancillary data.
+
+ * VHOST_USER_SET_VRING_FLAG
+
+      Id: 18
+      Equivalent ioctl: N/A
+      Master payload: vring state description
+
+      Set the flag(enable or disable) in the vring, the vhost user backend
+      enable or disable the vring according to state.num. Olny legal if feature
+      bit VHOST_USER_F_PROTOCOL_FEATURES is present in VHOST_USER_GET_FEATURE
+      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
+      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when state.num is
+      1, otherwise, the vring is disabled.
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 9cd6c05..5fa341c 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState *nc)
 
     return vhost_net;
 }
+
+int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
+{
+    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
+        struct vhost_net *net = get_vhost_net(nc);
+        const VhostOps *vhost_ops = net->dev.vhost_ops;
+        if (vhost_ops->vhost_backend_mq_set_vring_flag)
+            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev, enable);
+    }
+
+    return 0;
+}
+
 #else
 struct vhost_net *vhost_net_init(VhostNetOptions *options)
 {
@@ -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
 {
     return 0;
 }
+
+int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
+{
+    return 0;
+}
 #endif
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 3af6faf..272b77d 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
     }
 
     if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
+        vhost_set_vring_flag(nc->peer, 1);
         return 0;
     }
 
@@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
     }
 
     if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
+        vhost_set_vring_flag(nc->peer, 0);
         return 0;
     }
 
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index fb11d4c..d806ce2 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -25,7 +25,8 @@
 
 #define VHOST_MEMORY_MAX_NREGIONS    8
 #define VHOST_USER_F_PROTOCOL_FEATURES 30
-#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
+#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
+#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
 
 typedef enum VhostUserRequest {
     VHOST_USER_NONE = 0,
@@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
     VHOST_USER_SET_VRING_ERR = 14,
     VHOST_USER_GET_PROTOCOL_FEATURES = 15,
     VHOST_USER_SET_PROTOCOL_FEATURES = 16,
+    VHOST_USER_SET_VRING_FLAG = 18,
     VHOST_USER_MAX
 } VhostUserRequest;
 
@@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
     return 0;
 }
 
+static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned int enable)
+{
+    VhostUserMsg msg = { 0 };
+    int err;
+
+    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
+
+    if ((dev->backend_features & ( 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
+        return -1;
+
+    if ((dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
+        return -1;
+
+    msg.request = VHOST_USER_SET_VRING_FLAG;
+    msg.flags = VHOST_USER_VERSION;
+    /* Set the virt queue pair index */
+    msg.state.index = dev->vq_index / 2;
+    msg.state.num = enable;
+    msg.size = sizeof msg.state;
+
+    err = vhost_user_write(dev, &msg, NULL, 0);
+    if (err < 0) {
+        return err;
+    }
+
+    return 0;
+}
+
 static int vhost_user_cleanup(struct vhost_dev *dev)
 {
     assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
@@ -412,5 +442,6 @@ const VhostOps user_ops = {
         .backend_type = VHOST_BACKEND_TYPE_USER,
         .vhost_call = vhost_user_call,
         .vhost_backend_init = vhost_user_init,
-        .vhost_backend_cleanup = vhost_user_cleanup
+        .vhost_backend_cleanup = vhost_user_cleanup,
+        .vhost_backend_mq_set_vring_flag = vhost_user_set_vring_flag,
         };
diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
index e472f29..c394147 100644
--- a/include/hw/virtio/vhost-backend.h
+++ b/include/hw/virtio/vhost-backend.h
@@ -24,12 +24,14 @@ typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
              void *arg);
 typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
 typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
+typedef int (*vhost_backend_mq_set_vring_flag)(struct vhost_dev *dev, unsigned int enable);
 
 typedef struct VhostOps {
     VhostBackendType backend_type;
     vhost_call vhost_call;
     vhost_backend_init vhost_backend_init;
     vhost_backend_cleanup vhost_backend_cleanup;
+    vhost_backend_mq_set_vring_flag vhost_backend_mq_set_vring_flag;
 } VhostOps;
 
 extern const VhostOps user_ops;
diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
index b1c18a3..9b76548 100644
--- a/include/net/vhost_net.h
+++ b/include/net/vhost_net.h
@@ -29,4 +29,5 @@ bool vhost_net_virtqueue_pending(VHostNetState *net, int n);
 void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
                               int idx, bool mask);
 VHostNetState *get_vhost_net(NetClientState *nc);
+int vhost_set_vring_flag(NetClientState * nc, unsigned int enable);
 #endif
-- 
1.8.4.2

^ permalink raw reply related	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 1/2] vhost-user: add " Ouyang Changchun
@ 2015-08-13  9:18     ` Michael S. Tsirkin
  2015-08-13 10:24       ` Maxime Leroy
                         ` (3 more replies)
  0 siblings, 4 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-13  9:18 UTC (permalink / raw)
  To: Ouyang Changchun
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, thomas.long

On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> Based on patch by Nikolay Nikolaev:
> Vhost-user will implement the multi queue support in a similar way
> to what vhost already has - a separate thread for each queue.
> To enable the multi queue functionality - a new command line parameter
> "queues" is introduced for the vhost-user netdev.
> 
> The RESET_OWNER change is based on commit:
>    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> If it is reverted, the patch need update for it accordingly.
> 
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> ---
> Changes since v5:
>  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
> 
> Changes since v4:
>  - remove the unnecessary trailing '\n'
> 
> Changes since v3:
>  - fix one typo and wrap one long line
> 
> Changes since v2:
>  - fix vq index issue for set_vring_call
>    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
>    thus it could be a random value. The random value leads to crash in vhost after passing down
>    to vhost, as vhost use this random value to index an array index.
>  - fix the typo in the doc and description
>  - address vq index for reset_owner
> 
> Changes since v1:
>  - use s->nc.info_str when bringing up/down the backend
> 
>  docs/specs/vhost-user.txt |  7 ++++++-
>  hw/net/vhost_net.c        |  3 ++-
>  hw/virtio/vhost-user.c    | 11 ++++++++++-
>  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>  qapi-schema.json          |  6 +++++-
>  qemu-options.hx           |  5 +++--
>  6 files changed, 50 insertions(+), 19 deletions(-)
> 
> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> index 70da3b1..9390f89 100644
> --- a/docs/specs/vhost-user.txt
> +++ b/docs/specs/vhost-user.txt
> @@ -135,6 +135,11 @@ As older slaves don't support negotiating protocol features,
>  a feature bit was dedicated for this purpose:
>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
>  
> +Multi queue support
> +-------------------
> +The protocol supports multiple queues by setting all index fields in the sent
> +messages to a properly calculated value.
> +
>  Message types
>  -------------
>  
> @@ -198,7 +203,7 @@ Message types
>  
>        Id: 4
>        Equivalent ioctl: VHOST_RESET_OWNER
> -      Master payload: N/A
> +      Master payload: vring state description
>  
>        Issued when a new connection is about to be closed. The Master will no
>        longer own this connection (and will usually close it).

This is an interface change, isn't it?
We can't make it unconditionally, need to make it dependent
on a protocol flag.


> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 1f25cb3..9cd6c05 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -159,6 +159,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
>  
>      net->dev.nvqs = 2;
>      net->dev.vqs = net->vqs;
> +    net->dev.vq_index = net->nc->queue_index;
>  
>      r = vhost_dev_init(&net->dev, options->opaque,
>                         options->backend_type, options->force);
> @@ -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
>          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
>              const VhostOps *vhost_ops = net->dev.vhost_ops;
>              int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> -                                          NULL);
> +                                          &file);
>              assert(r >= 0);
>          }
>      }
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index 27ba035..fb11d4c 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>          break;
>  
>      case VHOST_USER_SET_OWNER:
> +        break;
> +
>      case VHOST_USER_RESET_OWNER:
> +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
> +        msg.size = sizeof(m.state);
>          break;
>  
>      case VHOST_USER_SET_MEM_TABLE:
> @@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>      case VHOST_USER_SET_VRING_NUM:
>      case VHOST_USER_SET_VRING_BASE:
>          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
>          msg.size = sizeof(m.state);
>          break;
>  
>      case VHOST_USER_GET_VRING_BASE:
>          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
>          msg.size = sizeof(m.state);
>          need_reply = 1;
>          break;
>  
>      case VHOST_USER_SET_VRING_ADDR:
>          memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> +        msg.addr.index += dev->vq_index;
>          msg.size = sizeof(m.addr);
>          break;
>  
> @@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>      case VHOST_USER_SET_VRING_CALL:
>      case VHOST_USER_SET_VRING_ERR:
>          file = arg;
> -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> +        msg.u64 = (file->index + dev->vq_index) & VHOST_USER_VRING_IDX_MASK;
>          msg.size = sizeof(m.u64);
>          if (ioeventfd_enabled() && file->fd > 0) {
>              fds[fd_num++] = file->fd;
> @@ -322,6 +330,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>                  error_report("Received bad msg size.");
>                  return -1;
>              }
> +            msg.state.index -= dev->vq_index;
>              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
>              break;
>          default:
> diff --git a/net/vhost-user.c b/net/vhost-user.c
> index 1d86a2b..904d8af 100644
> --- a/net/vhost-user.c
> +++ b/net/vhost-user.c
> @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque, int event)
>      case CHR_EVENT_OPENED:
>          vhost_user_start(s);
>          net_vhost_link_down(s, false);
> -        error_report("chardev \"%s\" went up", s->chr->label);
> +        error_report("chardev \"%s\" went up", s->nc.info_str);
>          break;
>      case CHR_EVENT_CLOSED:
>          net_vhost_link_down(s, true);
>          vhost_user_stop(s);
> -        error_report("chardev \"%s\" went down", s->chr->label);
> +        error_report("chardev \"%s\" went down", s->nc.info_str);
>          break;
>      }
>  }
>  
>  static int net_vhost_user_init(NetClientState *peer, const char *device,
> -                               const char *name, CharDriverState *chr)
> +                               const char *name, CharDriverState *chr,
> +                               uint32_t queues)
>  {
>      NetClientState *nc;
>      VhostUserState *s;
> +    int i;
>  
> -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> +    for (i = 0; i < queues; i++) {
> +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
>  
> -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> -             chr->label);
> +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> +                 i, chr->label);
>  
> -    s = DO_UPCAST(VhostUserState, nc, nc);
> +        s = DO_UPCAST(VhostUserState, nc, nc);
>  
> -    /* We don't provide a receive callback */
> -    s->nc.receive_disabled = 1;
> -    s->chr = chr;
> -
> -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> +        /* We don't provide a receive callback */
> +        s->nc.receive_disabled = 1;
> +        s->chr = chr;
> +        s->nc.queue_index = i;
>  
> +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> +    }
>      return 0;
>  }
>  
> @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)


There are two problems here:

1. we don't really know that the backend
   is able to support the requested number of queues.
   If not, everything will fail, silently.
   A new message to query the # of queues could help, though
   I'm not sure what can be done on failure. Fail connection?

2. each message (e.g. set memory table) is sent multiple times,
   on the same socket.



>  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
>                          NetClientState *peer)
>  {
> +    uint32_t queues;
>      const NetdevVhostUserOptions *vhost_user_opts;
>      CharDriverState *chr;
>  
> @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
>          return -1;
>      }
>  
> +    /* number of queues for multiqueue */
> +    if (vhost_user_opts->has_queues) {
> +        queues = vhost_user_opts->queues;
> +    } else {
> +        queues = 1;
> +    }
>  
> -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
>  }
> diff --git a/qapi-schema.json b/qapi-schema.json
> index f97ffa1..51e40ce 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2444,12 +2444,16 @@
>  #
>  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
>  #
> +# @queues: #optional number of queues to be created for multiqueue vhost-user
> +#          (default: 1) (Since 2.5)
> +#
>  # Since 2.1
>  ##
>  { 'struct': 'NetdevVhostUserOptions',
>    'data': {
>      'chardev':        'str',
> -    '*vhostforce':    'bool' } }
> +    '*vhostforce':    'bool',
> +    '*queues':        'uint32' } }
>  
>  ##
>  # @NetClientOptions
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ec356f6..dad035e 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
>  netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
>  required hub automatically.
>  
> -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
>  
>  Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
>  be a unix domain socket backed one. The vhost-user uses a specifically defined
>  protocol to pass vhost ioctl replacement messages to an application on the other
>  end of the socket. On non-MSIX guests, the feature can be forced with
> -@var{vhostforce}.
> +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> +be created for multiqueue vhost-user.
>  
>  Example:
>  @example
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue Ouyang Changchun
@ 2015-08-13  9:22     ` Michael S. Tsirkin
  2015-08-24  1:50       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
  2015-09-01  9:16       ` [Qemu-devel] " Yuanhan Liu
  0 siblings, 2 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-13  9:22 UTC (permalink / raw)
  To: Ouyang Changchun
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, thomas.long

On Wed, Aug 12, 2015 at 02:25:42PM +0800, Ouyang Changchun wrote:
> This patch is based on top of "vhost-user: protocol updates" series
> proposed earlier by Michael S. Tsirkin.
> 
> Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
> actual virt queue, which is similar to attach/detach queue for tap device.
> virtio driver on guest doesn't have to use max virt queue pair, it could
> enable any number of virt queue ranging from 1 to max virt queue pair.
> 
> It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.
> 
> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> ---
> This is added since v5
> 
>  docs/specs/vhost-user.txt         | 17 +++++++++++++++++
>  hw/net/vhost_net.c                | 18 ++++++++++++++++++
>  hw/net/virtio-net.c               |  2 ++
>  hw/virtio/vhost-user.c            | 35 +++++++++++++++++++++++++++++++++--
>  include/hw/virtio/vhost-backend.h |  2 ++
>  include/net/vhost_net.h           |  1 +
>  6 files changed, 73 insertions(+), 2 deletions(-)
> 
> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> index 9390f89..cca3e5b 100644
> --- a/docs/specs/vhost-user.txt
> +++ b/docs/specs/vhost-user.txt
> @@ -135,6 +135,10 @@ As older slaves don't support negotiating protocol features,
>  a feature bit was dedicated for this purpose:
>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
>  
> +The Slave uses vring flag to notify the vhost-user whether one virtq is enabled
> +or not. This request doesn't require replies:
> +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> +
>  Multi queue support
>  -------------------
>  The protocol supports multiple queues by setting all index fields in the sent
> @@ -306,3 +310,16 @@ Message types
>        Bits (0-7) of the payload contain the vring index. Bit 8 is the
>        invalid FD flag. This flag is set when there is no file descriptor
>        in the ancillary data.
> +
> + * VHOST_USER_SET_VRING_FLAG
> +
> +      Id: 18
> +      Equivalent ioctl: N/A
> +      Master payload: vring state description
> +
> +      Set the flag(enable or disable) in the vring, the vhost user backend
> +      enable or disable the vring according to state.num. Olny legal if feature
> +      bit VHOST_USER_F_PROTOCOL_FEATURES is present in VHOST_USER_GET_FEATURE
> +      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
> +      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when state.num is
> +      1, otherwise, the vring is disabled.
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 9cd6c05..5fa341c 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState *nc)
>  
>      return vhost_net;
>  }
> +
> +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> +{
> +    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> +        struct vhost_net *net = get_vhost_net(nc);
> +        const VhostOps *vhost_ops = net->dev.vhost_ops;
> +        if (vhost_ops->vhost_backend_mq_set_vring_flag)
> +            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev, enable);
> +    }
> +
> +    return 0;
> +}
> +
>  #else
>  struct vhost_net *vhost_net_init(VhostNetOptions *options)
>  {
> @@ -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
>  {
>      return 0;
>  }
> +
> +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> +{
> +    return 0;
> +}
>  #endif
> diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> index 3af6faf..272b77d 100644
> --- a/hw/net/virtio-net.c
> +++ b/hw/net/virtio-net.c
> @@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
>      }
>  
>      if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> +        vhost_set_vring_flag(nc->peer, 1);
>          return 0;
>      }
>  
> @@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
>      }
>  
>      if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
> +        vhost_set_vring_flag(nc->peer, 0);
>          return 0;
>      }
>  
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index fb11d4c..d806ce2 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -25,7 +25,8 @@
>  
>  #define VHOST_MEMORY_MAX_NREGIONS    8
>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
>  
>  typedef enum VhostUserRequest {
>      VHOST_USER_NONE = 0,
> @@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
>      VHOST_USER_SET_VRING_ERR = 14,
>      VHOST_USER_GET_PROTOCOL_FEATURES = 15,
>      VHOST_USER_SET_PROTOCOL_FEATURES = 16,
> +    VHOST_USER_SET_VRING_FLAG = 18,
>      VHOST_USER_MAX
>  } VhostUserRequest;
>  
> @@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
>      return 0;
>  }
>  
> +static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned int enable)
> +{
> +    VhostUserMsg msg = { 0 };
> +    int err;
> +
> +    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> +
> +    if ((dev->backend_features & ( 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
> +        return -1;
> +
> +    if ((dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
> +        return -1;
> +
> +    msg.request = VHOST_USER_SET_VRING_FLAG;
> +    msg.flags = VHOST_USER_VERSION;
> +    /* Set the virt queue pair index */
> +    msg.state.index = dev->vq_index / 2;

Thinking about this, this means that the index value is specific to virtio net.
This seems wrong.

> +    msg.state.num = enable;
> +    msg.size = sizeof msg.state;
> +
> +    err = vhost_user_write(dev, &msg, NULL, 0);
> +    if (err < 0) {
> +        return err;
> +    }
> +
> +    return 0;
> +}
> +
>  static int vhost_user_cleanup(struct vhost_dev *dev)
>  {
>      assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> @@ -412,5 +442,6 @@ const VhostOps user_ops = {
>          .backend_type = VHOST_BACKEND_TYPE_USER,
>          .vhost_call = vhost_user_call,
>          .vhost_backend_init = vhost_user_init,
> -        .vhost_backend_cleanup = vhost_user_cleanup
> +        .vhost_backend_cleanup = vhost_user_cleanup,
> +        .vhost_backend_mq_set_vring_flag = vhost_user_set_vring_flag,
>          };
> diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
> index e472f29..c394147 100644
> --- a/include/hw/virtio/vhost-backend.h
> +++ b/include/hw/virtio/vhost-backend.h
> @@ -24,12 +24,14 @@ typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
>               void *arg);
>  typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
>  typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
> +typedef int (*vhost_backend_mq_set_vring_flag)(struct vhost_dev *dev, unsigned int enable);
>  
>  typedef struct VhostOps {
>      VhostBackendType backend_type;
>      vhost_call vhost_call;
>      vhost_backend_init vhost_backend_init;
>      vhost_backend_cleanup vhost_backend_cleanup;
> +    vhost_backend_mq_set_vring_flag vhost_backend_mq_set_vring_flag;
>  } VhostOps;
>  
>  extern const VhostOps user_ops;
> diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> index b1c18a3..9b76548 100644
> --- a/include/net/vhost_net.h
> +++ b/include/net/vhost_net.h
> @@ -29,4 +29,5 @@ bool vhost_net_virtqueue_pending(VHostNetState *net, int n);
>  void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
>                                int idx, bool mask);
>  VHostNetState *get_vhost_net(NetClientState *nc);
> +int vhost_set_vring_flag(NetClientState * nc, unsigned int enable);
>  #endif
> -- 
> 1.8.4.2
> 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-13  9:18     ` Michael S. Tsirkin
@ 2015-08-13 10:24       ` Maxime Leroy
  2015-08-13 10:55         ` Michael S. Tsirkin
  2015-08-25  3:25       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
                         ` (2 subsequent siblings)
  3 siblings, 1 reply; 44+ messages in thread
From: Maxime Leroy @ 2015-08-13 10:24 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, Thibaut Collet, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, Ouyang Changchun

On Thu, Aug 13, 2015 at 11:18 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
>> Based on patch by Nikolay Nikolaev:
>> Vhost-user will implement the multi queue support in a similar way
>> to what vhost already has - a separate thread for each queue.
>> To enable the multi queue functionality - a new command line parameter
>> "queues" is introduced for the vhost-user netdev.
>>
>> The RESET_OWNER change is based on commit:
>>    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
>> If it is reverted, the patch need update for it accordingly.
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>> ---
>> Changes since v5:
>>  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
>>
>> Changes since v4:
>>  - remove the unnecessary trailing '\n'
>>
>> Changes since v3:
>>  - fix one typo and wrap one long line
>>
>> Changes since v2:
>>  - fix vq index issue for set_vring_call
>>    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
>>    thus it could be a random value. The random value leads to crash in vhost after passing down
>>    to vhost, as vhost use this random value to index an array index.
>>  - fix the typo in the doc and description
>>  - address vq index for reset_owner
>>
>> Changes since v1:
>>  - use s->nc.info_str when bringing up/down the backend
>>
>>  docs/specs/vhost-user.txt |  7 ++++++-
>>  hw/net/vhost_net.c        |  3 ++-
>>  hw/virtio/vhost-user.c    | 11 ++++++++++-
>>  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>>  qapi-schema.json          |  6 +++++-
>>  qemu-options.hx           |  5 +++--
>>  6 files changed, 50 insertions(+), 19 deletions(-)
>>
>> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
>> index 70da3b1..9390f89 100644
>> --- a/docs/specs/vhost-user.txt
>> +++ b/docs/specs/vhost-user.txt
>> @@ -135,6 +135,11 @@ As older slaves don't support negotiating protocol features,
>>  a feature bit was dedicated for this purpose:
>>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
>>
>> +Multi queue support
>> +-------------------
>> +The protocol supports multiple queues by setting all index fields in the sent
>> +messages to a properly calculated value.
>> +
>>  Message types
>>  -------------
>>
>> @@ -198,7 +203,7 @@ Message types
>>
>>        Id: 4
>>        Equivalent ioctl: VHOST_RESET_OWNER
>> -      Master payload: N/A
>> +      Master payload: vring state description
>>
>>        Issued when a new connection is about to be closed. The Master will no
>>        longer own this connection (and will usually close it).
>
> This is an interface change, isn't it?
> We can't make it unconditionally, need to make it dependent
> on a protocol flag.

Agree. It can potential break vhost-user driver implementation
checking the size of the message. We should not change the vhost-user
protocol without a new protocol flag.

I think the first issue here that VHOST_RESET_OWNER should happen on
vhost_dev_cleanup and not in  vhost_net_stop_one.

VHOST_RESET_OWNER should be the counter part of VHOST_SET_OWNER. So it
don't need to have a payload like VHOST_SET_OWNER.

Thus I agree with this email
(http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg05971.html)

Maybe should we use an other message to tell to the backend that the
vring is not anymore available in vhost_net_stop_one ?

Maxime

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-13 10:24       ` Maxime Leroy
@ 2015-08-13 10:55         ` Michael S. Tsirkin
  0 siblings, 0 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-13 10:55 UTC (permalink / raw)
  To: Maxime Leroy
  Cc: snabb-devel, Thibaut Collet, qemu-devel, Nikolay Nikolaev,
	Luke Gorrie, thomas.long, Ouyang Changchun

On Thu, Aug 13, 2015 at 12:24:16PM +0200, Maxime Leroy wrote:
> On Thu, Aug 13, 2015 at 11:18 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> >> Based on patch by Nikolay Nikolaev:
> >> Vhost-user will implement the multi queue support in a similar way
> >> to what vhost already has - a separate thread for each queue.
> >> To enable the multi queue functionality - a new command line parameter
> >> "queues" is introduced for the vhost-user netdev.
> >>
> >> The RESET_OWNER change is based on commit:
> >>    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> >> If it is reverted, the patch need update for it accordingly.
> >>
> >> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> >> ---
> >> Changes since v5:
> >>  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
> >>
> >> Changes since v4:
> >>  - remove the unnecessary trailing '\n'
> >>
> >> Changes since v3:
> >>  - fix one typo and wrap one long line
> >>
> >> Changes since v2:
> >>  - fix vq index issue for set_vring_call
> >>    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
> >>    thus it could be a random value. The random value leads to crash in vhost after passing down
> >>    to vhost, as vhost use this random value to index an array index.
> >>  - fix the typo in the doc and description
> >>  - address vq index for reset_owner
> >>
> >> Changes since v1:
> >>  - use s->nc.info_str when bringing up/down the backend
> >>
> >>  docs/specs/vhost-user.txt |  7 ++++++-
> >>  hw/net/vhost_net.c        |  3 ++-
> >>  hw/virtio/vhost-user.c    | 11 ++++++++++-
> >>  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> >>  qapi-schema.json          |  6 +++++-
> >>  qemu-options.hx           |  5 +++--
> >>  6 files changed, 50 insertions(+), 19 deletions(-)
> >>
> >> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> >> index 70da3b1..9390f89 100644
> >> --- a/docs/specs/vhost-user.txt
> >> +++ b/docs/specs/vhost-user.txt
> >> @@ -135,6 +135,11 @@ As older slaves don't support negotiating protocol features,
> >>  a feature bit was dedicated for this purpose:
> >>  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> >>
> >> +Multi queue support
> >> +-------------------
> >> +The protocol supports multiple queues by setting all index fields in the sent
> >> +messages to a properly calculated value.
> >> +
> >>  Message types
> >>  -------------
> >>
> >> @@ -198,7 +203,7 @@ Message types
> >>
> >>        Id: 4
> >>        Equivalent ioctl: VHOST_RESET_OWNER
> >> -      Master payload: N/A
> >> +      Master payload: vring state description
> >>
> >>        Issued when a new connection is about to be closed. The Master will no
> >>        longer own this connection (and will usually close it).
> >
> > This is an interface change, isn't it?
> > We can't make it unconditionally, need to make it dependent
> > on a protocol flag.
> 
> Agree. It can potential break vhost-user driver implementation
> checking the size of the message. We should not change the vhost-user
> protocol without a new protocol flag.
> 
> I think the first issue here that VHOST_RESET_OWNER should happen on
> vhost_dev_cleanup and not in  vhost_net_stop_one.
> 
> VHOST_RESET_OWNER should be the counter part of VHOST_SET_OWNER. So it
> don't need to have a payload like VHOST_SET_OWNER.
> 
> Thus I agree with this email
> (http://lists.nongnu.org/archive/html/qemu-devel/2015-07/msg05971.html)
> 
> Maybe should we use an other message to tell to the backend that the
> vring is not anymore available in vhost_net_stop_one ?
> 
> Maxime

I think the cleanest fix is to rename this message to e.g.
VHOST_RESET_DEVICE. This way we won't break existing users.

-- 
MST

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-08-13  9:22     ` Michael S. Tsirkin
@ 2015-08-24  1:50       ` Ouyang, Changchun
  2015-09-01  9:16       ` [Qemu-devel] " Yuanhan Liu
  1 sibling, 0 replies; 44+ messages in thread
From: Ouyang, Changchun @ 2015-08-24  1:50 UTC (permalink / raw)
  To: snabb-devel
  Cc: Liu, Yuanhan, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

Hi Michael,

> -----Original Message-----
> From: snabb-devel@googlegroups.com [mailto:snabb-
> devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> Sent: Thursday, August 13, 2015 5:23 PM
> To: Ouyang, Changchun
> Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas
> Subject: [snabb-devel] Re: [PATCH v6 2/2] vhost-user: new protocol feature
> for multi queue
> 
> On Wed, Aug 12, 2015 at 02:25:42PM +0800, Ouyang Changchun wrote:
> > This patch is based on top of "vhost-user: protocol updates" series
> > proposed earlier by Michael S. Tsirkin.
> >
> > Use new message VHOST_USER_SET_VRING_FLAG to enable and disable
> an
> > actual virt queue, which is similar to attach/detach queue for tap device.
> > virtio driver on guest doesn't have to use max virt queue pair, it
> > could enable any number of virt queue ranging from 1 to max virt queue
> pair.
> >
> > It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.
> >
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > ---
> > This is added since v5
> >
> >  docs/specs/vhost-user.txt         | 17 +++++++++++++++++
> >  hw/net/vhost_net.c                | 18 ++++++++++++++++++
> >  hw/net/virtio-net.c               |  2 ++
> >  hw/virtio/vhost-user.c            | 35
> +++++++++++++++++++++++++++++++++--
> >  include/hw/virtio/vhost-backend.h |  2 ++
> >  include/net/vhost_net.h           |  1 +
> >  6 files changed, 73 insertions(+), 2 deletions(-)
> >
> > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > index 9390f89..cca3e5b 100644
> > --- a/docs/specs/vhost-user.txt
> > +++ b/docs/specs/vhost-user.txt
> > @@ -135,6 +135,10 @@ As older slaves don't support negotiating
> > protocol features,  a feature bit was dedicated for this purpose:
> >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> >
> > +The Slave uses vring flag to notify the vhost-user whether one virtq
> > +is enabled or not. This request doesn't require replies:
> > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > +
> >  Multi queue support
> >  -------------------
> >  The protocol supports multiple queues by setting all index fields in
> > the sent @@ -306,3 +310,16 @@ Message types
> >        Bits (0-7) of the payload contain the vring index. Bit 8 is the
> >        invalid FD flag. This flag is set when there is no file descriptor
> >        in the ancillary data.
> > +
> > + * VHOST_USER_SET_VRING_FLAG
> > +
> > +      Id: 18
> > +      Equivalent ioctl: N/A
> > +      Master payload: vring state description
> > +
> > +      Set the flag(enable or disable) in the vring, the vhost user backend
> > +      enable or disable the vring according to state.num. Olny legal if feature
> > +      bit VHOST_USER_F_PROTOCOL_FEATURES is present in
> VHOST_USER_GET_FEATURE
> > +      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
> > +      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when
> state.num is
> > +      1, otherwise, the vring is disabled.
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > 9cd6c05..5fa341c 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState
> *nc)
> >
> >      return vhost_net;
> >  }
> > +
> > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable) {
> > +    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> > +        struct vhost_net *net = get_vhost_net(nc);
> > +        const VhostOps *vhost_ops = net->dev.vhost_ops;
> > +        if (vhost_ops->vhost_backend_mq_set_vring_flag)
> > +            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev,
> enable);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  #else
> >  struct vhost_net *vhost_net_init(VhostNetOptions *options)  { @@
> > -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)  {
> >      return 0;
> >  }
> > +
> > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable) {
> > +    return 0;
> > +}
> >  #endif
> > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index
> > 3af6faf..272b77d 100644
> > --- a/hw/net/virtio-net.c
> > +++ b/hw/net/virtio-net.c
> > @@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
> >      }
> >
> >      if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> > +        vhost_set_vring_flag(nc->peer, 1);
> >          return 0;
> >      }
> >
> > @@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
> >      }
> >
> >      if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
> > +        vhost_set_vring_flag(nc->peer, 0);
> >          return 0;
> >      }
> >
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > fb11d4c..d806ce2 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -25,7 +25,8 @@
> >
> >  #define VHOST_MEMORY_MAX_NREGIONS    8
> >  #define VHOST_USER_F_PROTOCOL_FEATURES 30 -#define
> > VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2 #define
> > +VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
> >
> >  typedef enum VhostUserRequest {
> >      VHOST_USER_NONE = 0,
> > @@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
> >      VHOST_USER_SET_VRING_ERR = 14,
> >      VHOST_USER_GET_PROTOCOL_FEATURES = 15,
> >      VHOST_USER_SET_PROTOCOL_FEATURES = 16,
> > +    VHOST_USER_SET_VRING_FLAG = 18,
> >      VHOST_USER_MAX
> >  } VhostUserRequest;
> >
> > @@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev,
> void *opaque)
> >      return 0;
> >  }
> >
> > +static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned
> > +int enable) {
> > +    VhostUserMsg msg = { 0 };
> > +    int err;
> > +
> > +    assert(dev->vhost_ops->backend_type ==
> VHOST_BACKEND_TYPE_USER);
> > +
> > +    if ((dev->backend_features & ( 1ULL <<
> VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
> > +        return -1;
> > +
> > +    if ((dev->protocol_features & (1ULL <<
> VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
> > +        return -1;
> > +
> > +    msg.request = VHOST_USER_SET_VRING_FLAG;
> > +    msg.flags = VHOST_USER_VERSION;
> > +    /* Set the virt queue pair index */
> > +    msg.state.index = dev->vq_index / 2;
> 
> Thinking about this, this means that the index value is specific to virtio net.
> This seems wrong.

So you suggest it should remove the ' / 2' for the msg.state.index above, as follows:
msg.state.index = dev->vq_index;
do I understand it correctly?

Thanks 
Changchun

> 
> > +    msg.state.num = enable;
> > +    msg.size = sizeof msg.state;
> > +
> > +    err = vhost_user_write(dev, &msg, NULL, 0);
> > +    if (err < 0) {
> > +        return err;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  static int vhost_user_cleanup(struct vhost_dev *dev)  {
> >      assert(dev->vhost_ops->backend_type ==
> VHOST_BACKEND_TYPE_USER);
> > @@ -412,5 +442,6 @@ const VhostOps user_ops = {
> >          .backend_type = VHOST_BACKEND_TYPE_USER,
> >          .vhost_call = vhost_user_call,
> >          .vhost_backend_init = vhost_user_init,
> > -        .vhost_backend_cleanup = vhost_user_cleanup
> > +        .vhost_backend_cleanup = vhost_user_cleanup,
> > +        .vhost_backend_mq_set_vring_flag = vhost_user_set_vring_flag,
> >          };
> > diff --git a/include/hw/virtio/vhost-backend.h
> > b/include/hw/virtio/vhost-backend.h
> > index e472f29..c394147 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -24,12 +24,14 @@ typedef int (*vhost_call)(struct vhost_dev *dev,
> unsigned long int request,
> >               void *arg);
> >  typedef int (*vhost_backend_init)(struct vhost_dev *dev, void
> > *opaque);  typedef int (*vhost_backend_cleanup)(struct vhost_dev
> > *dev);
> > +typedef int (*vhost_backend_mq_set_vring_flag)(struct vhost_dev *dev,
> > +unsigned int enable);
> >
> >  typedef struct VhostOps {
> >      VhostBackendType backend_type;
> >      vhost_call vhost_call;
> >      vhost_backend_init vhost_backend_init;
> >      vhost_backend_cleanup vhost_backend_cleanup;
> > +    vhost_backend_mq_set_vring_flag vhost_backend_mq_set_vring_flag;
> >  } VhostOps;
> >
> >  extern const VhostOps user_ops;
> > diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h index
> > b1c18a3..9b76548 100644
> > --- a/include/net/vhost_net.h
> > +++ b/include/net/vhost_net.h
> > @@ -29,4 +29,5 @@ bool vhost_net_virtqueue_pending(VHostNetState
> *net,
> > int n);  void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice
> *dev,
> >                                int idx, bool mask);  VHostNetState
> > *get_vhost_net(NetClientState *nc);
> > +int vhost_set_vring_flag(NetClientState * nc, unsigned int enable);
> >  #endif
> > --
> > 1.8.4.2
> >
> 
> --
> You received this message because you are subscribed to the Google Groups
> "Snabb Switch development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to snabb-devel+unsubscribe@googlegroups.com.
> To post to this group, send an email to snabb-devel@googlegroups.com.
> Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-13  9:18     ` Michael S. Tsirkin
  2015-08-13 10:24       ` Maxime Leroy
@ 2015-08-25  3:25       ` Ouyang, Changchun
  2015-08-27 13:05         ` Michael S. Tsirkin
  2015-09-01  9:13       ` [Qemu-devel] " Yuanhan Liu
  2015-09-07 11:07       ` Marcel Apfelbaum
  3 siblings, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-08-25  3:25 UTC (permalink / raw)
  To: Michael S. Tsirkin, snabb-devel
  Cc: Liu, Yuanhan, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

Hi Michael,

> -----Original Message-----
> From: snabb-devel@googlegroups.com [mailto:snabb-
> devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> Sent: Thursday, August 13, 2015 5:19 PM
> To: Ouyang, Changchun
> Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas
> Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> support
> 
> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > Based on patch by Nikolay Nikolaev:
> > Vhost-user will implement the multi queue support in a similar way to
> > what vhost already has - a separate thread for each queue.
> > To enable the multi queue functionality - a new command line parameter
> > "queues" is introduced for the vhost-user netdev.
> >
> > The RESET_OWNER change is based on commit:
> >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > If it is reverted, the patch need update for it accordingly.
> >
> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > ---
> > Changes since v5:
> >  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
> >
> > Changes since v4:
> >  - remove the unnecessary trailing '\n'
> >
> > Changes since v3:
> >  - fix one typo and wrap one long line
> >
> > Changes since v2:
> >  - fix vq index issue for set_vring_call
> >    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not
> initialized before it is used,
> >    thus it could be a random value. The random value leads to crash in vhost
> after passing down
> >    to vhost, as vhost use this random value to index an array index.
> >  - fix the typo in the doc and description
> >  - address vq index for reset_owner
> >
> > Changes since v1:
> >  - use s->nc.info_str when bringing up/down the backend
> >
> >  docs/specs/vhost-user.txt |  7 ++++++-
> >  hw/net/vhost_net.c        |  3 ++-
> >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> >  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> >  qapi-schema.json          |  6 +++++-
> >  qemu-options.hx           |  5 +++--
> >  6 files changed, 50 insertions(+), 19 deletions(-)
> >
> > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > index 70da3b1..9390f89 100644
> > --- a/docs/specs/vhost-user.txt
> > +++ b/docs/specs/vhost-user.txt
> > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > protocol features,  a feature bit was dedicated for this purpose:
> >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> >
> > +Multi queue support
> > +-------------------
> > +The protocol supports multiple queues by setting all index fields in
> > +the sent messages to a properly calculated value.
> > +
> >  Message types
> >  -------------
> >
> > @@ -198,7 +203,7 @@ Message types
> >
> >        Id: 4
> >        Equivalent ioctl: VHOST_RESET_OWNER
> > -      Master payload: N/A
> > +      Master payload: vring state description
> >
> >        Issued when a new connection is about to be closed. The Master will no
> >        longer own this connection (and will usually close it).
> 
> This is an interface change, isn't it?
> We can't make it unconditionally, need to make it dependent on a protocol
> flag.
> 
> 
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > 1f25cb3..9cd6c05 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -159,6 +159,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
> > *options)
> >
> >      net->dev.nvqs = 2;
> >      net->dev.vqs = net->vqs;
> > +    net->dev.vq_index = net->nc->queue_index;
> >
> >      r = vhost_dev_init(&net->dev, options->opaque,
> >                         options->backend_type, options->force); @@
> > -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
> >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> >              int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > -                                          NULL);
> > +                                          &file);
> >              assert(r >= 0);
> >          }
> >      }
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > 27ba035..fb11d4c 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >          break;
> >
> >      case VHOST_USER_SET_OWNER:
> > +        break;
> > +
> >      case VHOST_USER_RESET_OWNER:
> > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> > +        msg.size = sizeof(m.state);
> >          break;
> >
> >      case VHOST_USER_SET_MEM_TABLE:
> > @@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >      case VHOST_USER_SET_VRING_NUM:
> >      case VHOST_USER_SET_VRING_BASE:
> >          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >          msg.size = sizeof(m.state);
> >          break;
> >
> >      case VHOST_USER_GET_VRING_BASE:
> >          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >          msg.size = sizeof(m.state);
> >          need_reply = 1;
> >          break;
> >
> >      case VHOST_USER_SET_VRING_ADDR:
> >          memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > +        msg.addr.index += dev->vq_index;
> >          msg.size = sizeof(m.addr);
> >          break;
> >
> > @@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >      case VHOST_USER_SET_VRING_CALL:
> >      case VHOST_USER_SET_VRING_ERR:
> >          file = arg;
> > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > +        msg.u64 = (file->index + dev->vq_index) &
> > + VHOST_USER_VRING_IDX_MASK;
> >          msg.size = sizeof(m.u64);
> >          if (ioeventfd_enabled() && file->fd > 0) {
> >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@ static int
> > vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> >                  error_report("Received bad msg size.");
> >                  return -1;
> >              }
> > +            msg.state.index -= dev->vq_index;
> >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> >              break;
> >          default:
> > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > 1d86a2b..904d8af 100644
> > --- a/net/vhost-user.c
> > +++ b/net/vhost-user.c
> > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque,
> int event)
> >      case CHR_EVENT_OPENED:
> >          vhost_user_start(s);
> >          net_vhost_link_down(s, false);
> > -        error_report("chardev \"%s\" went up", s->chr->label);
> > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> >          break;
> >      case CHR_EVENT_CLOSED:
> >          net_vhost_link_down(s, true);
> >          vhost_user_stop(s);
> > -        error_report("chardev \"%s\" went down", s->chr->label);
> > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> >          break;
> >      }
> >  }
> >
> >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > -                               const char *name, CharDriverState *chr)
> > +                               const char *name, CharDriverState *chr,
> > +                               uint32_t queues)
> >  {
> >      NetClientState *nc;
> >      VhostUserState *s;
> > +    int i;
> >
> > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> name);
> > +    for (i = 0; i < queues; i++) {
> > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > + name);
> >
> > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > -             chr->label);
> > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > +                 i, chr->label);
> >
> > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > +        s = DO_UPCAST(VhostUserState, nc, nc);
> >
> > -    /* We don't provide a receive callback */
> > -    s->nc.receive_disabled = 1;
> > -    s->chr = chr;
> > -
> > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> s);
> > +        /* We don't provide a receive callback */
> > +        s->nc.receive_disabled = 1;
> > +        s->chr = chr;
> > +        s->nc.queue_index = i;
> >
> > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> s);
> > +    }
> >      return 0;
> >  }
> >
> > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts,
> > void *opaque)
> 
> 
> There are two problems here:
> 
> 1. we don't really know that the backend
>    is able to support the requested number of queues.
>    If not, everything will fail, silently.
>    A new message to query the # of queues could help, though
>    I'm not sure what can be done on failure. Fail connection?
> 
> 2. each message (e.g. set memory table) is sent multiple times,
>    on the same socket.
> 
I think it is tough to resolve these 2 comments, as the current message is either vhost-dev based or virt-queue based,
The multiple queues(pair) feature use multiple vhost-devs to implement itself.
For #1
So the queue number is something should be seen in the upper level of vhost-dev rather than inside the vhost-dev.
For each vhost-net, there are 2 virt-queues, one is for Rx the other is for Tx.
introduce the virt-queue pair number into the vhost-dev? But I don't think it is good, as for each vhost-dev, there is only one
virt-queue pair.

Where should I put the virt-queue pair number to? I don't get the perfect answer till now. Any suggestion is welcome.

Could we assume the vhost backend has the ability to create enough virt-queue pair(e.g. 0x8000 is the max) if qemu require
Vhost backend to do it. If it is correct, we don't need get virt-queue pair number from vhost backend, as vhost backend can
Create all virt-queue pair required by qemu.
The virtio frontend(on guest) has the flexibility to enable which virt-queue according to its own capability, qemu can do it by using
Set_vring_flag message to notify vhost backend.   

For #2 
The memory table message is also vhost-dev based, it wouldn't hurt we send it a few times, vhost backend could
Keep it vhost-dev based too, or keep it once(keep it when first time and ignore in rest messages from the same connected-fd)
Any other good suggestion is welcome too :-)

> 
> 
> >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> >                          NetClientState *peer)  {
> > +    uint32_t queues;
> >      const NetdevVhostUserOptions *vhost_user_opts;
> >      CharDriverState *chr;
> >
> > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions
> *opts, const char *name,
> >          return -1;
> >      }
> >
> > +    /* number of queues for multiqueue */
> > +    if (vhost_user_opts->has_queues) {
> > +        queues = vhost_user_opts->queues;
> > +    } else {
> > +        queues = 1;
> > +    }
> >
> > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > + queues);
> >  }
> > diff --git a/qapi-schema.json b/qapi-schema.json index
> > f97ffa1..51e40ce 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -2444,12 +2444,16 @@
> >  #
> >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> false).
> >  #
> > +# @queues: #optional number of queues to be created for multiqueue
> vhost-user
> > +#          (default: 1) (Since 2.5)
> > +#
> >  # Since 2.1
> >  ##
> >  { 'struct': 'NetdevVhostUserOptions',
> >    'data': {
> >      'chardev':        'str',
> > -    '*vhostforce':    'bool' } }
> > +    '*vhostforce':    'bool',
> > +    '*queues':        'uint32' } }
> >
> >  ##
> >  # @NetClientOptions
> > diff --git a/qemu-options.hx b/qemu-options.hx index ec356f6..dad035e
> > 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a
> > QEMU "vlan" instead of a single  netdev.  @code{-net} and
> > @code{-device} with parameter @option{vlan} create the  required hub
> automatically.
> >
> > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > +@item -netdev
> > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> >
> >  Establish a vhost-user netdev, backed by a chardev @var{id}. The
> > chardev should  be a unix domain socket backed one. The vhost-user
> > uses a specifically defined  protocol to pass vhost ioctl replacement
> > messages to an application on the other  end of the socket. On
> > non-MSIX guests, the feature can be forced with -@var{vhostforce}.
> > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
> > +queues to be created for multiqueue vhost-user.
> >
> >  Example:
> >  @example
> > --
> > 1.8.4.2
> >
> 
> --
> You received this message because you are subscribed to the Google Groups
> "Snabb Switch development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to snabb-devel+unsubscribe@googlegroups.com.
> To post to this group, send an email to snabb-devel@googlegroups.com.
> Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-25  3:25       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
@ 2015-08-27 13:05         ` Michael S. Tsirkin
  2015-08-28  1:53           ` Ouyang, Changchun
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-27 13:05 UTC (permalink / raw)
  To: Ouyang, Changchun
  Cc: snabb-devel, Liu, Yuanhan, thibaut.collet, qemu-devel,
	n.nikolaev, luke, Long, Thomas

On Tue, Aug 25, 2015 at 03:25:54AM +0000, Ouyang, Changchun wrote:
> Hi Michael,
> 
> > -----Original Message-----
> > From: snabb-devel@googlegroups.com [mailto:snabb-
> > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > Sent: Thursday, August 13, 2015 5:19 PM
> > To: Ouyang, Changchun
> > Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > luke@snabb.co; Long, Thomas
> > Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> > support
> > 
> > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > Based on patch by Nikolay Nikolaev:
> > > Vhost-user will implement the multi queue support in a similar way to
> > > what vhost already has - a separate thread for each queue.
> > > To enable the multi queue functionality - a new command line parameter
> > > "queues" is introduced for the vhost-user netdev.
> > >
> > > The RESET_OWNER change is based on commit:
> > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > If it is reverted, the patch need update for it accordingly.
> > >
> > > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > ---
> > > Changes since v5:
> > >  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
> > >
> > > Changes since v4:
> > >  - remove the unnecessary trailing '\n'
> > >
> > > Changes since v3:
> > >  - fix one typo and wrap one long line
> > >
> > > Changes since v2:
> > >  - fix vq index issue for set_vring_call
> > >    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not
> > initialized before it is used,
> > >    thus it could be a random value. The random value leads to crash in vhost
> > after passing down
> > >    to vhost, as vhost use this random value to index an array index.
> > >  - fix the typo in the doc and description
> > >  - address vq index for reset_owner
> > >
> > > Changes since v1:
> > >  - use s->nc.info_str when bringing up/down the backend
> > >
> > >  docs/specs/vhost-user.txt |  7 ++++++-
> > >  hw/net/vhost_net.c        |  3 ++-
> > >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> > >  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> > >  qapi-schema.json          |  6 +++++-
> > >  qemu-options.hx           |  5 +++--
> > >  6 files changed, 50 insertions(+), 19 deletions(-)
> > >
> > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > > index 70da3b1..9390f89 100644
> > > --- a/docs/specs/vhost-user.txt
> > > +++ b/docs/specs/vhost-user.txt
> > > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > > protocol features,  a feature bit was dedicated for this purpose:
> > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > >
> > > +Multi queue support
> > > +-------------------
> > > +The protocol supports multiple queues by setting all index fields in
> > > +the sent messages to a properly calculated value.
> > > +
> > >  Message types
> > >  -------------
> > >
> > > @@ -198,7 +203,7 @@ Message types
> > >
> > >        Id: 4
> > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > -      Master payload: N/A
> > > +      Master payload: vring state description
> > >
> > >        Issued when a new connection is about to be closed. The Master will no
> > >        longer own this connection (and will usually close it).
> > 
> > This is an interface change, isn't it?
> > We can't make it unconditionally, need to make it dependent on a protocol
> > flag.


Pls remember to fix this one.

> > 
> > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > 1f25cb3..9cd6c05 100644
> > > --- a/hw/net/vhost_net.c
> > > +++ b/hw/net/vhost_net.c
> > > @@ -159,6 +159,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
> > > *options)
> > >
> > >      net->dev.nvqs = 2;
> > >      net->dev.vqs = net->vqs;
> > > +    net->dev.vq_index = net->nc->queue_index;
> > >
> > >      r = vhost_dev_init(&net->dev, options->opaque,
> > >                         options->backend_type, options->force); @@
> > > -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
> > >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> > >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> > >              int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > > -                                          NULL);
> > > +                                          &file);
> > >              assert(r >= 0);
> > >          }
> > >      }
> > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > > 27ba035..fb11d4c 100644
> > > --- a/hw/virtio/vhost-user.c
> > > +++ b/hw/virtio/vhost-user.c
> > > @@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev *dev,
> > unsigned long int request,
> > >          break;
> > >
> > >      case VHOST_USER_SET_OWNER:
> > > +        break;
> > > +
> > >      case VHOST_USER_RESET_OWNER:
> > > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > +        msg.state.index += dev->vq_index;
> > > +        msg.size = sizeof(m.state);
> > >          break;
> > >
> > >      case VHOST_USER_SET_MEM_TABLE:
> > > @@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev *dev,
> > unsigned long int request,
> > >      case VHOST_USER_SET_VRING_NUM:
> > >      case VHOST_USER_SET_VRING_BASE:
> > >          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > +        msg.state.index += dev->vq_index;
> > >          msg.size = sizeof(m.state);
> > >          break;
> > >
> > >      case VHOST_USER_GET_VRING_BASE:
> > >          memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > +        msg.state.index += dev->vq_index;
> > >          msg.size = sizeof(m.state);
> > >          need_reply = 1;
> > >          break;
> > >
> > >      case VHOST_USER_SET_VRING_ADDR:
> > >          memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > > +        msg.addr.index += dev->vq_index;
> > >          msg.size = sizeof(m.addr);
> > >          break;
> > >
> > > @@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev *dev,
> > unsigned long int request,
> > >      case VHOST_USER_SET_VRING_CALL:
> > >      case VHOST_USER_SET_VRING_ERR:
> > >          file = arg;
> > > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > > +        msg.u64 = (file->index + dev->vq_index) &
> > > + VHOST_USER_VRING_IDX_MASK;
> > >          msg.size = sizeof(m.u64);
> > >          if (ioeventfd_enabled() && file->fd > 0) {
> > >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@ static int
> > > vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> > >                  error_report("Received bad msg size.");
> > >                  return -1;
> > >              }
> > > +            msg.state.index -= dev->vq_index;
> > >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> > >              break;
> > >          default:
> > > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > > 1d86a2b..904d8af 100644
> > > --- a/net/vhost-user.c
> > > +++ b/net/vhost-user.c
> > > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque,
> > int event)
> > >      case CHR_EVENT_OPENED:
> > >          vhost_user_start(s);
> > >          net_vhost_link_down(s, false);
> > > -        error_report("chardev \"%s\" went up", s->chr->label);
> > > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> > >          break;
> > >      case CHR_EVENT_CLOSED:
> > >          net_vhost_link_down(s, true);
> > >          vhost_user_stop(s);
> > > -        error_report("chardev \"%s\" went down", s->chr->label);
> > > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> > >          break;
> > >      }
> > >  }

BTW this seems pretty hacky: you get multiple messages when one
client connects. Why add multiple event listeners to the same
chat device?


> > >
> > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > -                               const char *name, CharDriverState *chr)
> > > +                               const char *name, CharDriverState *chr,
> > > +                               uint32_t queues)
> > >  {
> > >      NetClientState *nc;
> > >      VhostUserState *s;
> > > +    int i;
> > >
> > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > name);
> > > +    for (i = 0; i < queues; i++) {
> > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > > + name);
> > >
> > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > -             chr->label);
> > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > +                 i, chr->label);
> > >
> > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > >
> > > -    /* We don't provide a receive callback */
> > > -    s->nc.receive_disabled = 1;
> > > -    s->chr = chr;
> > > -
> > > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> > s);
> > > +        /* We don't provide a receive callback */
> > > +        s->nc.receive_disabled = 1;
> > > +        s->chr = chr;
> > > +        s->nc.queue_index = i;
> > >
> > > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> > s);
> > > +    }
> > >      return 0;
> > >  }
> > >
> > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts,
> > > void *opaque)
> > 
> > 
> > There are two problems here:
> > 
> > 1. we don't really know that the backend
> >    is able to support the requested number of queues.
> >    If not, everything will fail, silently.
> >    A new message to query the # of queues could help, though
> >    I'm not sure what can be done on failure. Fail connection?
> > 
> > 2. each message (e.g. set memory table) is sent multiple times,
> >    on the same socket.
> > 
> I think it is tough to resolve these 2 comments, as the current message is either vhost-dev based or virt-queue based,
> The multiple queues(pair) feature use multiple vhost-devs to implement itself.
> For #1
> So the queue number is something should be seen in the upper level of vhost-dev rather than inside the vhost-dev.
> For each vhost-net, there are 2 virt-queues, one is for Rx the other is for Tx.
> introduce the virt-queue pair number into the vhost-dev? But I don't think it is good, as for each vhost-dev, there is only one
> virt-queue pair.
> 
> Where should I put the virt-queue pair number to? I don't get the perfect answer till now. Any suggestion is welcome.
> 
> Could we assume the vhost backend has the ability to create enough virt-queue pair(e.g. 0x8000 is the max) if qemu require
> Vhost backend to do it. If it is correct, we don't need get virt-queue pair number from vhost backend, as vhost backend can
> Create all virt-queue pair required by qemu.
> The virtio frontend(on guest) has the flexibility to enable which virt-queue according to its own capability, qemu can do it by using
> Set_vring_flag message to notify vhost backend.   

I'm reluctant to agree to this. Implementations tend to get this wrong,
e.g. they would only test with 2 queues and assume everything is OK.
With an explicit message, this seems more robust.

Why is it so hard to implement?  User specifies queues=X.
Can't we simply validate that backend supports this # of queues?


> For #2 
> The memory table message is also vhost-dev based, it wouldn't hurt we send it a few times, vhost backend could
> Keep it vhost-dev based too, or keep it once(keep it when first time and ignore in rest messages from the same connected-fd)
> Any other good suggestion is welcome too :-)

Add code in vhost-user to skip sending the useless messages?  Yes they
seem harmless but implementations tend to develop dependencies on such
bugs, then we get to maintain them forever.

> > 
> > 
> > >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > >                          NetClientState *peer)  {
> > > +    uint32_t queues;
> > >      const NetdevVhostUserOptions *vhost_user_opts;
> > >      CharDriverState *chr;
> > >
> > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions
> > *opts, const char *name,
> > >          return -1;
> > >      }
> > >
> > > +    /* number of queues for multiqueue */
> > > +    if (vhost_user_opts->has_queues) {
> > > +        queues = vhost_user_opts->queues;
> > > +    } else {
> > > +        queues = 1;
> > > +    }
> > >
> > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > + queues);
> > >  }
> > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > f97ffa1..51e40ce 100644
> > > --- a/qapi-schema.json
> > > +++ b/qapi-schema.json
> > > @@ -2444,12 +2444,16 @@
> > >  #
> > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> > false).
> > >  #
> > > +# @queues: #optional number of queues to be created for multiqueue
> > vhost-user
> > > +#          (default: 1) (Since 2.5)
> > > +#
> > >  # Since 2.1
> > >  ##
> > >  { 'struct': 'NetdevVhostUserOptions',
> > >    'data': {
> > >      'chardev':        'str',
> > > -    '*vhostforce':    'bool' } }
> > > +    '*vhostforce':    'bool',
> > > +    '*queues':        'uint32' } }
> > >
> > >  ##
> > >  # @NetClientOptions
> > > diff --git a/qemu-options.hx b/qemu-options.hx index ec356f6..dad035e
> > > 100644
> > > --- a/qemu-options.hx
> > > +++ b/qemu-options.hx
> > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a
> > > QEMU "vlan" instead of a single  netdev.  @code{-net} and
> > > @code{-device} with parameter @option{vlan} create the  required hub
> > automatically.
> > >
> > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > +@item -netdev
> > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > >
> > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The
> > > chardev should  be a unix domain socket backed one. The vhost-user
> > > uses a specifically defined  protocol to pass vhost ioctl replacement
> > > messages to an application on the other  end of the socket. On
> > > non-MSIX guests, the feature can be forced with -@var{vhostforce}.
> > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
> > > +queues to be created for multiqueue vhost-user.
> > >
> > >  Example:
> > >  @example
> > > --
> > > 1.8.4.2
> > >
> > 
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Snabb Switch development" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to snabb-devel+unsubscribe@googlegroups.com.
> > To post to this group, send an email to snabb-devel@googlegroups.com.
> > Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-27 13:05         ` Michael S. Tsirkin
@ 2015-08-28  1:53           ` Ouyang, Changchun
  2015-08-30  6:16             ` Michael S. Tsirkin
  0 siblings, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-08-28  1:53 UTC (permalink / raw)
  To: snabb-devel, Michael S. Tsirkin
  Cc: Liu, Yuanhan, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

Hi Michael,

Thanks for your response!

> -----Original Message-----
> From: snabb-devel@googlegroups.com [mailto:snabb-
> devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> Sent: Thursday, August 27, 2015 9:05 PM
> To: Ouyang, Changchun
> Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas; Liu, Yuanhan
> Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> support
> 
> On Tue, Aug 25, 2015 at 03:25:54AM +0000, Ouyang, Changchun wrote:
> > Hi Michael,
> >
> > > -----Original Message-----
> > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > Sent: Thursday, August 13, 2015 5:19 PM
> > > To: Ouyang, Changchun
> > > Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > luke@snabb.co; Long, Thomas
> > > Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > queue support
> > >
> > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > Based on patch by Nikolay Nikolaev:
> > > > Vhost-user will implement the multi queue support in a similar way
> > > > to what vhost already has - a separate thread for each queue.
> > > > To enable the multi queue functionality - a new command line
> > > > parameter "queues" is introduced for the vhost-user netdev.
> > > >
> > > > The RESET_OWNER change is based on commit:
> > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > If it is reverted, the patch need update for it accordingly.
> > > >
> > > > Signed-off-by: Nikolay Nikolaev
> > > > <n.nikolaev@virtualopensystems.com>
> > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > ---
> > > > Changes since v5:
> > > >  - fix the message descption for VHOST_RESET_OWNER in vhost-user
> > > > txt
> > > >
> > > > Changes since v4:
> > > >  - remove the unnecessary trailing '\n'
> > > >
> > > > Changes since v3:
> > > >  - fix one typo and wrap one long line
> > > >
> > > > Changes since v2:
> > > >  - fix vq index issue for set_vring_call
> > > >    When it is the case of VHOST_SET_VRING_CALL, The vq_index is
> > > > not
> > > initialized before it is used,
> > > >    thus it could be a random value. The random value leads to
> > > > crash in vhost
> > > after passing down
> > > >    to vhost, as vhost use this random value to index an array index.
> > > >  - fix the typo in the doc and description
> > > >  - address vq index for reset_owner
> > > >
> > > > Changes since v1:
> > > >  - use s->nc.info_str when bringing up/down the backend
> > > >
> > > >  docs/specs/vhost-user.txt |  7 ++++++-
> > > >  hw/net/vhost_net.c        |  3 ++-
> > > >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> > > >  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> > > >  qapi-schema.json          |  6 +++++-
> > > >  qemu-options.hx           |  5 +++--
> > > >  6 files changed, 50 insertions(+), 19 deletions(-)
> > > >
> > > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > > > index 70da3b1..9390f89 100644
> > > > --- a/docs/specs/vhost-user.txt
> > > > +++ b/docs/specs/vhost-user.txt
> > > > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > > > protocol features,  a feature bit was dedicated for this purpose:
> > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > >
> > > > +Multi queue support
> > > > +-------------------
> > > > +The protocol supports multiple queues by setting all index fields
> > > > +in the sent messages to a properly calculated value.
> > > > +
> > > >  Message types
> > > >  -------------
> > > >
> > > > @@ -198,7 +203,7 @@ Message types
> > > >
> > > >        Id: 4
> > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > -      Master payload: N/A
> > > > +      Master payload: vring state description
> > > >
> > > >        Issued when a new connection is about to be closed. The Master
> will no
> > > >        longer own this connection (and will usually close it).
> > >
> > > This is an interface change, isn't it?
> > > We can't make it unconditionally, need to make it dependent on a
> > > protocol flag.
> 
> 
> Pls remember to fix this one.
> 
> > >
> > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > 1f25cb3..9cd6c05 100644
> > > > --- a/hw/net/vhost_net.c
> > > > +++ b/hw/net/vhost_net.c
> > > > @@ -159,6 +159,7 @@ struct vhost_net
> > > > *vhost_net_init(VhostNetOptions
> > > > *options)
> > > >
> > > >      net->dev.nvqs = 2;
> > > >      net->dev.vqs = net->vqs;
> > > > +    net->dev.vq_index = net->nc->queue_index;
> > > >
> > > >      r = vhost_dev_init(&net->dev, options->opaque,
> > > >                         options->backend_type, options->force); @@
> > > > -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net
> *net,
> > > >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> > > >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > >              int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > > > -                                          NULL);
> > > > +                                          &file);
> > > >              assert(r >= 0);
> > > >          }
> > > >      }
> > > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > > > 27ba035..fb11d4c 100644
> > > > --- a/hw/virtio/vhost-user.c
> > > > +++ b/hw/virtio/vhost-user.c
> > > > @@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev
> > > > *dev,
> > > unsigned long int request,
> > > >          break;
> > > >
> > > >      case VHOST_USER_SET_OWNER:
> > > > +        break;
> > > > +
> > > >      case VHOST_USER_RESET_OWNER:
> > > > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > > +        msg.state.index += dev->vq_index;
> > > > +        msg.size = sizeof(m.state);
> > > >          break;
> > > >
> > > >      case VHOST_USER_SET_MEM_TABLE:
> > > > @@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev
> > > > *dev,
> > > unsigned long int request,
> > > >      case VHOST_USER_SET_VRING_NUM:
> > > >      case VHOST_USER_SET_VRING_BASE:
> > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > vhost_vring_state));
> > > > +        msg.state.index += dev->vq_index;
> > > >          msg.size = sizeof(m.state);
> > > >          break;
> > > >
> > > >      case VHOST_USER_GET_VRING_BASE:
> > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > vhost_vring_state));
> > > > +        msg.state.index += dev->vq_index;
> > > >          msg.size = sizeof(m.state);
> > > >          need_reply = 1;
> > > >          break;
> > > >
> > > >      case VHOST_USER_SET_VRING_ADDR:
> > > >          memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > > > +        msg.addr.index += dev->vq_index;
> > > >          msg.size = sizeof(m.addr);
> > > >          break;
> > > >
> > > > @@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev
> > > > *dev,
> > > unsigned long int request,
> > > >      case VHOST_USER_SET_VRING_CALL:
> > > >      case VHOST_USER_SET_VRING_ERR:
> > > >          file = arg;
> > > > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > > > +        msg.u64 = (file->index + dev->vq_index) &
> > > > + VHOST_USER_VRING_IDX_MASK;
> > > >          msg.size = sizeof(m.u64);
> > > >          if (ioeventfd_enabled() && file->fd > 0) {
> > > >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@ static
> > > > int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> > > >                  error_report("Received bad msg size.");
> > > >                  return -1;
> > > >              }
> > > > +            msg.state.index -= dev->vq_index;
> > > >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> > > >              break;
> > > >          default:
> > > > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > > > 1d86a2b..904d8af 100644
> > > > --- a/net/vhost-user.c
> > > > +++ b/net/vhost-user.c
> > > > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void
> > > > *opaque,
> > > int event)
> > > >      case CHR_EVENT_OPENED:
> > > >          vhost_user_start(s);
> > > >          net_vhost_link_down(s, false);
> > > > -        error_report("chardev \"%s\" went up", s->chr->label);
> > > > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> > > >          break;
> > > >      case CHR_EVENT_CLOSED:
> > > >          net_vhost_link_down(s, true);
> > > >          vhost_user_stop(s);
> > > > -        error_report("chardev \"%s\" went down", s->chr->label);
> > > > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> > > >          break;
> > > >      }
> > > >  }
> 
> BTW this seems pretty hacky: you get multiple messages when one client
> connects. Why add multiple event listeners to the same chat device?
> 
> 
> > > >
> > > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > > -                               const char *name, CharDriverState *chr)
> > > > +                               const char *name, CharDriverState *chr,
> > > > +                               uint32_t queues)
> > > >  {
> > > >      NetClientState *nc;
> > > >      VhostUserState *s;
> > > > +    int i;
> > > >
> > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > > name);
> > > > +    for (i = 0; i < queues; i++) {
> > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > + device, name);
> > > >
> > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > -             chr->label);
> > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > > +                 i, chr->label);
> > > >
> > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > >
> > > > -    /* We don't provide a receive callback */
> > > > -    s->nc.receive_disabled = 1;
> > > > -    s->chr = chr;
> > > > -
> > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> net_vhost_user_event,
> > > s);
> > > > +        /* We don't provide a receive callback */
> > > > +        s->nc.receive_disabled = 1;
> > > > +        s->chr = chr;
> > > > +        s->nc.queue_index = i;
> > > >
> > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > > + net_vhost_user_event,
> > > s);
> > > > +    }
> > > >      return 0;
> > > >  }
> > > >
> > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> *opts,
> > > > void *opaque)
> > >
> > >
> > > There are two problems here:
> > >
> > > 1. we don't really know that the backend
> > >    is able to support the requested number of queues.
> > >    If not, everything will fail, silently.
> > >    A new message to query the # of queues could help, though
> > >    I'm not sure what can be done on failure. Fail connection?
> > >
> > > 2. each message (e.g. set memory table) is sent multiple times,
> > >    on the same socket.
> > >
> > I think it is tough to resolve these 2 comments, as the current
> > message is either vhost-dev based or virt-queue based, The multiple
> queues(pair) feature use multiple vhost-devs to implement itself.
> > For #1
> > So the queue number is something should be seen in the upper level of
> vhost-dev rather than inside the vhost-dev.
> > For each vhost-net, there are 2 virt-queues, one is for Rx the other is for Tx.
> > introduce the virt-queue pair number into the vhost-dev? But I don't
> > think it is good, as for each vhost-dev, there is only one virt-queue pair.
> >
> > Where should I put the virt-queue pair number to? I don't get the perfect
> answer till now. Any suggestion is welcome.
> >
> > Could we assume the vhost backend has the ability to create enough
> > virt-queue pair(e.g. 0x8000 is the max) if qemu require Vhost backend
> > to do it. If it is correct, we don't need get virt-queue pair number from
> vhost backend, as vhost backend can Create all virt-queue pair required by
> qemu.
> > The virtio frontend(on guest) has the flexibility to enable which virt-queue
> according to its own capability, qemu can do it by using
> > Set_vring_flag message to notify vhost backend.
> 
> I'm reluctant to agree to this. Implementations tend to get this wrong, e.g.
> they would only test with 2 queues and assume everything is OK.
> With an explicit message, this seems more robust.
> 
> Why is it so hard to implement?  User specifies queues=X.
> Can't we simply validate that backend supports this # of queues?

Yes exactly in the qemu, we use qeueus=X to specify the virt-queue pair number.
In my previous comments, I am talking about how to resolve such scenario: 
vhost backend specify the queues=Y(Y != X, e.g. X = 8, Y = 4), how vhost backend tell
qemu that it only has the capability of max virt-queue pair is 4, and qemu need update its
max queue number according to its own parameter and the max value from vhost back end.

Do you think whether this scenario makes sense or not?
If yes, then we should consider extend new message to allow vhost backend communicate 
Its virt-queue number to qemu.
More than that, either we need change codes to allow each net_client has more than 
1 virt-queue pair(==2 virt-queue, one for Rx, the other for Tx), 
Or another better solution for that? 

> 
> 
> > For #2
> > The memory table message is also vhost-dev based, it wouldn't hurt we
> > send it a few times, vhost backend could Keep it vhost-dev based too,
> > or keep it once(keep it when first time and ignore in rest messages
> > from the same connected-fd) Any other good suggestion is welcome too
> > :-)
> 
> Add code in vhost-user to skip sending the useless messages?  Yes they
> seem harmless but implementations tend to develop dependencies on such
> bugs, then we get to maintain them forever.

Considering we use multiple vhost_net(multiple net_client) to fulfill multiple virt-queue pairs.
So only the first virt-queue pair will send the set-memory-table, others won't do it.
Is that ok? so apparently each net client will have difference in message count.
The first net client will have the message of set memory table, others have not. 

Thanks
Changchun

> 
> > >
> > >
> > > >  int net_init_vhost_user(const NetClientOptions *opts, const char
> *name,
> > > >                          NetClientState *peer)  {
> > > > +    uint32_t queues;
> > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > >      CharDriverState *chr;
> > > >
> > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> > > > NetClientOptions
> > > *opts, const char *name,
> > > >          return -1;
> > > >      }
> > > >
> > > > +    /* number of queues for multiqueue */
> > > > +    if (vhost_user_opts->has_queues) {
> > > > +        queues = vhost_user_opts->queues;
> > > > +    } else {
> > > > +        queues = 1;
> > > > +    }
> > > >
> > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > + queues);
> > > >  }
> > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > f97ffa1..51e40ce 100644
> > > > --- a/qapi-schema.json
> > > > +++ b/qapi-schema.json
> > > > @@ -2444,12 +2444,16 @@
> > > >  #
> > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> > > false).
> > > >  #
> > > > +# @queues: #optional number of queues to be created for
> > > > +multiqueue
> > > vhost-user
> > > > +#          (default: 1) (Since 2.5)
> > > > +#
> > > >  # Since 2.1
> > > >  ##
> > > >  { 'struct': 'NetdevVhostUserOptions',
> > > >    'data': {
> > > >      'chardev':        'str',
> > > > -    '*vhostforce':    'bool' } }
> > > > +    '*vhostforce':    'bool',
> > > > +    '*queues':        'uint32' } }
> > > >
> > > >  ##
> > > >  # @NetClientOptions
> > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > ec356f6..dad035e
> > > > 100644
> > > > --- a/qemu-options.hx
> > > > +++ b/qemu-options.hx
> > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC
> > > > to a QEMU "vlan" instead of a single  netdev.  @code{-net} and
> > > > @code{-device} with parameter @option{vlan} create the  required
> > > > hub
> > > automatically.
> > > >
> > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > +@item -netdev
> > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > >
> > > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The
> > > > chardev should  be a unix domain socket backed one. The vhost-user
> > > > uses a specifically defined  protocol to pass vhost ioctl
> > > > replacement messages to an application on the other  end of the
> > > > socket. On non-MSIX guests, the feature can be forced with -
> @var{vhostforce}.
> > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
> > > > +queues to be created for multiqueue vhost-user.
> > > >
> > > >  Example:
> > > >  @example
> > > > --
> > > > 1.8.4.2
> > > >
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Snabb Switch development" group.
> > > To unsubscribe from this group and stop receiving emails from it,
> > > send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > To post to this group, send an email to snabb-devel@googlegroups.com.
> > > Visit this group at http://groups.google.com/group/snabb-devel.
> 
> --
> You received this message because you are subscribed to the Google Groups
> "Snabb Switch development" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to snabb-devel+unsubscribe@googlegroups.com.
> To post to this group, send an email to snabb-devel@googlegroups.com.
> Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-28  1:53           ` Ouyang, Changchun
@ 2015-08-30  6:16             ` Michael S. Tsirkin
  2015-08-31  8:29               ` Ouyang, Changchun
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-30  6:16 UTC (permalink / raw)
  To: Ouyang, Changchun
  Cc: snabb-devel, Liu, Yuanhan, thibaut.collet, qemu-devel,
	n.nikolaev, luke, Long, Thomas

On Fri, Aug 28, 2015 at 01:53:39AM +0000, Ouyang, Changchun wrote:
> Hi Michael,
> 
> Thanks for your response!
> 
> > -----Original Message-----
> > From: snabb-devel@googlegroups.com [mailto:snabb-
> > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > Sent: Thursday, August 27, 2015 9:05 PM
> > To: Ouyang, Changchun
> > Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > luke@snabb.co; Long, Thomas; Liu, Yuanhan
> > Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> > support
> > 
> > On Tue, Aug 25, 2015 at 03:25:54AM +0000, Ouyang, Changchun wrote:
> > > Hi Michael,
> > >
> > > > -----Original Message-----
> > > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > > Sent: Thursday, August 13, 2015 5:19 PM
> > > > To: Ouyang, Changchun
> > > > Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> > > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > > luke@snabb.co; Long, Thomas
> > > > Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > > queue support
> > > >
> > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > Based on patch by Nikolay Nikolaev:
> > > > > Vhost-user will implement the multi queue support in a similar way
> > > > > to what vhost already has - a separate thread for each queue.
> > > > > To enable the multi queue functionality - a new command line
> > > > > parameter "queues" is introduced for the vhost-user netdev.
> > > > >
> > > > > The RESET_OWNER change is based on commit:
> > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > If it is reverted, the patch need update for it accordingly.
> > > > >
> > > > > Signed-off-by: Nikolay Nikolaev
> > > > > <n.nikolaev@virtualopensystems.com>
> > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > > ---
> > > > > Changes since v5:
> > > > >  - fix the message descption for VHOST_RESET_OWNER in vhost-user
> > > > > txt
> > > > >
> > > > > Changes since v4:
> > > > >  - remove the unnecessary trailing '\n'
> > > > >
> > > > > Changes since v3:
> > > > >  - fix one typo and wrap one long line
> > > > >
> > > > > Changes since v2:
> > > > >  - fix vq index issue for set_vring_call
> > > > >    When it is the case of VHOST_SET_VRING_CALL, The vq_index is
> > > > > not
> > > > initialized before it is used,
> > > > >    thus it could be a random value. The random value leads to
> > > > > crash in vhost
> > > > after passing down
> > > > >    to vhost, as vhost use this random value to index an array index.
> > > > >  - fix the typo in the doc and description
> > > > >  - address vq index for reset_owner
> > > > >
> > > > > Changes since v1:
> > > > >  - use s->nc.info_str when bringing up/down the backend
> > > > >
> > > > >  docs/specs/vhost-user.txt |  7 ++++++-
> > > > >  hw/net/vhost_net.c        |  3 ++-
> > > > >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> > > > >  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> > > > >  qapi-schema.json          |  6 +++++-
> > > > >  qemu-options.hx           |  5 +++--
> > > > >  6 files changed, 50 insertions(+), 19 deletions(-)
> > > > >
> > > > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > > > > index 70da3b1..9390f89 100644
> > > > > --- a/docs/specs/vhost-user.txt
> > > > > +++ b/docs/specs/vhost-user.txt
> > > > > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > > > > protocol features,  a feature bit was dedicated for this purpose:
> > > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > > >
> > > > > +Multi queue support
> > > > > +-------------------
> > > > > +The protocol supports multiple queues by setting all index fields
> > > > > +in the sent messages to a properly calculated value.
> > > > > +
> > > > >  Message types
> > > > >  -------------
> > > > >
> > > > > @@ -198,7 +203,7 @@ Message types
> > > > >
> > > > >        Id: 4
> > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > -      Master payload: N/A
> > > > > +      Master payload: vring state description
> > > > >
> > > > >        Issued when a new connection is about to be closed. The Master
> > will no
> > > > >        longer own this connection (and will usually close it).
> > > >
> > > > This is an interface change, isn't it?
> > > > We can't make it unconditionally, need to make it dependent on a
> > > > protocol flag.
> > 
> > 
> > Pls remember to fix this one.
> > 
> > > >
> > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > > 1f25cb3..9cd6c05 100644
> > > > > --- a/hw/net/vhost_net.c
> > > > > +++ b/hw/net/vhost_net.c
> > > > > @@ -159,6 +159,7 @@ struct vhost_net
> > > > > *vhost_net_init(VhostNetOptions
> > > > > *options)
> > > > >
> > > > >      net->dev.nvqs = 2;
> > > > >      net->dev.vqs = net->vqs;
> > > > > +    net->dev.vq_index = net->nc->queue_index;
> > > > >
> > > > >      r = vhost_dev_init(&net->dev, options->opaque,
> > > > >                         options->backend_type, options->force); @@
> > > > > -269,7 +270,7 @@ static void vhost_net_stop_one(struct vhost_net
> > *net,
> > > > >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> > > > >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > > >              int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > > > > -                                          NULL);
> > > > > +                                          &file);
> > > > >              assert(r >= 0);
> > > > >          }
> > > > >      }
> > > > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > > > > 27ba035..fb11d4c 100644
> > > > > --- a/hw/virtio/vhost-user.c
> > > > > +++ b/hw/virtio/vhost-user.c
> > > > > @@ -219,7 +219,12 @@ static int vhost_user_call(struct vhost_dev
> > > > > *dev,
> > > > unsigned long int request,
> > > > >          break;
> > > > >
> > > > >      case VHOST_USER_SET_OWNER:
> > > > > +        break;
> > > > > +
> > > > >      case VHOST_USER_RESET_OWNER:
> > > > > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > > > +        msg.state.index += dev->vq_index;
> > > > > +        msg.size = sizeof(m.state);
> > > > >          break;
> > > > >
> > > > >      case VHOST_USER_SET_MEM_TABLE:
> > > > > @@ -262,17 +267,20 @@ static int vhost_user_call(struct vhost_dev
> > > > > *dev,
> > > > unsigned long int request,
> > > > >      case VHOST_USER_SET_VRING_NUM:
> > > > >      case VHOST_USER_SET_VRING_BASE:
> > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > vhost_vring_state));
> > > > > +        msg.state.index += dev->vq_index;
> > > > >          msg.size = sizeof(m.state);
> > > > >          break;
> > > > >
> > > > >      case VHOST_USER_GET_VRING_BASE:
> > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > vhost_vring_state));
> > > > > +        msg.state.index += dev->vq_index;
> > > > >          msg.size = sizeof(m.state);
> > > > >          need_reply = 1;
> > > > >          break;
> > > > >
> > > > >      case VHOST_USER_SET_VRING_ADDR:
> > > > >          memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > > > > +        msg.addr.index += dev->vq_index;
> > > > >          msg.size = sizeof(m.addr);
> > > > >          break;
> > > > >
> > > > > @@ -280,7 +288,7 @@ static int vhost_user_call(struct vhost_dev
> > > > > *dev,
> > > > unsigned long int request,
> > > > >      case VHOST_USER_SET_VRING_CALL:
> > > > >      case VHOST_USER_SET_VRING_ERR:
> > > > >          file = arg;
> > > > > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > > > > +        msg.u64 = (file->index + dev->vq_index) &
> > > > > + VHOST_USER_VRING_IDX_MASK;
> > > > >          msg.size = sizeof(m.u64);
> > > > >          if (ioeventfd_enabled() && file->fd > 0) {
> > > > >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@ static
> > > > > int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> > > > >                  error_report("Received bad msg size.");
> > > > >                  return -1;
> > > > >              }
> > > > > +            msg.state.index -= dev->vq_index;
> > > > >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> > > > >              break;
> > > > >          default:
> > > > > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > > > > 1d86a2b..904d8af 100644
> > > > > --- a/net/vhost-user.c
> > > > > +++ b/net/vhost-user.c
> > > > > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void
> > > > > *opaque,
> > > > int event)
> > > > >      case CHR_EVENT_OPENED:
> > > > >          vhost_user_start(s);
> > > > >          net_vhost_link_down(s, false);
> > > > > -        error_report("chardev \"%s\" went up", s->chr->label);
> > > > > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> > > > >          break;
> > > > >      case CHR_EVENT_CLOSED:
> > > > >          net_vhost_link_down(s, true);
> > > > >          vhost_user_stop(s);
> > > > > -        error_report("chardev \"%s\" went down", s->chr->label);
> > > > > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> > > > >          break;
> > > > >      }
> > > > >  }
> > 
> > BTW this seems pretty hacky: you get multiple messages when one client
> > connects. Why add multiple event listeners to the same chat device?
> > 
> > 
> > > > >
> > > > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > > > -                               const char *name, CharDriverState *chr)
> > > > > +                               const char *name, CharDriverState *chr,
> > > > > +                               uint32_t queues)
> > > > >  {
> > > > >      NetClientState *nc;
> > > > >      VhostUserState *s;
> > > > > +    int i;
> > > > >
> > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > > > name);
> > > > > +    for (i = 0; i < queues; i++) {
> > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > > + device, name);
> > > > >
> > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > -             chr->label);
> > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > > > +                 i, chr->label);
> > > > >
> > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > >
> > > > > -    /* We don't provide a receive callback */
> > > > > -    s->nc.receive_disabled = 1;
> > > > > -    s->chr = chr;
> > > > > -
> > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> > net_vhost_user_event,
> > > > s);
> > > > > +        /* We don't provide a receive callback */
> > > > > +        s->nc.receive_disabled = 1;
> > > > > +        s->chr = chr;
> > > > > +        s->nc.queue_index = i;
> > > > >
> > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > > > + net_vhost_user_event,
> > > > s);
> > > > > +    }
> > > > >      return 0;
> > > > >  }
> > > > >
> > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> > *opts,
> > > > > void *opaque)
> > > >
> > > >
> > > > There are two problems here:
> > > >
> > > > 1. we don't really know that the backend
> > > >    is able to support the requested number of queues.
> > > >    If not, everything will fail, silently.
> > > >    A new message to query the # of queues could help, though
> > > >    I'm not sure what can be done on failure. Fail connection?
> > > >
> > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > >    on the same socket.
> > > >
> > > I think it is tough to resolve these 2 comments, as the current
> > > message is either vhost-dev based or virt-queue based, The multiple
> > queues(pair) feature use multiple vhost-devs to implement itself.
> > > For #1
> > > So the queue number is something should be seen in the upper level of
> > vhost-dev rather than inside the vhost-dev.
> > > For each vhost-net, there are 2 virt-queues, one is for Rx the other is for Tx.
> > > introduce the virt-queue pair number into the vhost-dev? But I don't
> > > think it is good, as for each vhost-dev, there is only one virt-queue pair.
> > >
> > > Where should I put the virt-queue pair number to? I don't get the perfect
> > answer till now. Any suggestion is welcome.
> > >
> > > Could we assume the vhost backend has the ability to create enough
> > > virt-queue pair(e.g. 0x8000 is the max) if qemu require Vhost backend
> > > to do it. If it is correct, we don't need get virt-queue pair number from
> > vhost backend, as vhost backend can Create all virt-queue pair required by
> > qemu.
> > > The virtio frontend(on guest) has the flexibility to enable which virt-queue
> > according to its own capability, qemu can do it by using
> > > Set_vring_flag message to notify vhost backend.
> > 
> > I'm reluctant to agree to this. Implementations tend to get this wrong, e.g.
> > they would only test with 2 queues and assume everything is OK.
> > With an explicit message, this seems more robust.
> > 
> > Why is it so hard to implement?  User specifies queues=X.
> > Can't we simply validate that backend supports this # of queues?
> 
> Yes exactly in the qemu, we use qeueus=X to specify the virt-queue pair number.
> In my previous comments, I am talking about how to resolve such scenario: 
> vhost backend specify the queues=Y(Y != X, e.g. X = 8, Y = 4), how vhost backend tell
> qemu that it only has the capability of max virt-queue pair is 4, and qemu need update its
> max queue number according to its own parameter and the max value from vhost back end.
> 
> Do you think whether this scenario makes sense or not?

No, I think that if we can't support the number requested by user,
QEMU can simply exit.

> If yes, then we should consider extend new message to allow vhost backend communicate 
> Its virt-queue number to qemu.

Yes, conditional on the mq protocol flag.

> More than that, either we need change codes to allow each net_client has more than 
> 1 virt-queue pair(==2 virt-queue, one for Rx, the other for Tx), 
> Or another better solution for that? 

I'm not sure why is that required for the above.

> > 
> > 
> > > For #2
> > > The memory table message is also vhost-dev based, it wouldn't hurt we
> > > send it a few times, vhost backend could Keep it vhost-dev based too,
> > > or keep it once(keep it when first time and ignore in rest messages
> > > from the same connected-fd) Any other good suggestion is welcome too
> > > :-)
> > 
> > Add code in vhost-user to skip sending the useless messages?  Yes they
> > seem harmless but implementations tend to develop dependencies on such
> > bugs, then we get to maintain them forever.
> 
> Considering we use multiple vhost_net(multiple net_client) to fulfill multiple virt-queue pairs.
> So only the first virt-queue pair will send the set-memory-table, others won't do it.
> Is that ok? so apparently each net client will have difference in message count.
> The first net client will have the message of set memory table, others have not. 
> 
> Thanks
> Changchun

But all these clients use the same unix domain socket, correct?
If so, I don't think it matters that internally in qemu they
use different net clients. From the external point of view,
it looks like a single message is sent on a single socket.

> > 
> > > >
> > > >
> > > > >  int net_init_vhost_user(const NetClientOptions *opts, const char
> > *name,
> > > > >                          NetClientState *peer)  {
> > > > > +    uint32_t queues;
> > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > >      CharDriverState *chr;
> > > > >
> > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> > > > > NetClientOptions
> > > > *opts, const char *name,
> > > > >          return -1;
> > > > >      }
> > > > >
> > > > > +    /* number of queues for multiqueue */
> > > > > +    if (vhost_user_opts->has_queues) {
> > > > > +        queues = vhost_user_opts->queues;
> > > > > +    } else {
> > > > > +        queues = 1;
> > > > > +    }
> > > > >
> > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > > + queues);
> > > > >  }
> > > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > > f97ffa1..51e40ce 100644
> > > > > --- a/qapi-schema.json
> > > > > +++ b/qapi-schema.json
> > > > > @@ -2444,12 +2444,16 @@
> > > > >  #
> > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> > > > false).
> > > > >  #
> > > > > +# @queues: #optional number of queues to be created for
> > > > > +multiqueue
> > > > vhost-user
> > > > > +#          (default: 1) (Since 2.5)
> > > > > +#
> > > > >  # Since 2.1
> > > > >  ##
> > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > >    'data': {
> > > > >      'chardev':        'str',
> > > > > -    '*vhostforce':    'bool' } }
> > > > > +    '*vhostforce':    'bool',
> > > > > +    '*queues':        'uint32' } }
> > > > >
> > > > >  ##
> > > > >  # @NetClientOptions
> > > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > > ec356f6..dad035e
> > > > > 100644
> > > > > --- a/qemu-options.hx
> > > > > +++ b/qemu-options.hx
> > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC
> > > > > to a QEMU "vlan" instead of a single  netdev.  @code{-net} and
> > > > > @code{-device} with parameter @option{vlan} create the  required
> > > > > hub
> > > > automatically.
> > > > >
> > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > +@item -netdev
> > > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > >
> > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The
> > > > > chardev should  be a unix domain socket backed one. The vhost-user
> > > > > uses a specifically defined  protocol to pass vhost ioctl
> > > > > replacement messages to an application on the other  end of the
> > > > > socket. On non-MSIX guests, the feature can be forced with -
> > @var{vhostforce}.
> > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
> > > > > +queues to be created for multiqueue vhost-user.
> > > > >
> > > > >  Example:
> > > > >  @example
> > > > > --
> > > > > 1.8.4.2
> > > > >
> > > >
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups "Snabb Switch development" group.
> > > > To unsubscribe from this group and stop receiving emails from it,
> > > > send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > > To post to this group, send an email to snabb-devel@googlegroups.com.
> > > > Visit this group at http://groups.google.com/group/snabb-devel.
> > 
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Snabb Switch development" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to snabb-devel+unsubscribe@googlegroups.com.
> > To post to this group, send an email to snabb-devel@googlegroups.com.
> > Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-05-28  1:23 [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Ouyang Changchun
  2015-07-08 14:29 ` Michael S. Tsirkin
  2015-08-12  6:25 ` [Qemu-devel] [PATCH v6 0/2] vhost-user " Ouyang Changchun
@ 2015-08-30 15:28 ` Marcel Apfelbaum
  2015-08-31  5:28   ` Ouyang, Changchun
  2 siblings, 1 reply; 44+ messages in thread
From: Marcel Apfelbaum @ 2015-08-30 15:28 UTC (permalink / raw)
  To: Ouyang Changchun, qemu-devel, mst
  Cc: luke, snabb-devel, thomas.long, n.nikolaev

On 05/28/2015 04:23 AM, Ouyang Changchun wrote:
> Based on patch by Nikolay Nikolaev:
> Vhost-user will implement the multi queue support in a similar way
> to what vhost already has - a separate thread for each queue.
> To enable the multi queue functionality - a new command line parameter
> "queues" is introduced for the vhost-user netdev.
>
> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
Hi,

Can you please share how you did you test it?
Was it the DPDK vhost-user example? (after the MQ patches, of course)
I ask because I tried to test it with no success so far.
Any pointers would be appreciated.

Thanks,
Marcel


> ---
> Changes since v4:
>   - remove the unnecessary trailing '\n'
>
> Changes since v3:
>   - fix one typo and wrap one long line
>
> Changes since v2:
>   - fix vq index issue for set_vring_call
>     When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
>     thus it could be a random value. The random value leads to crash in vhost after passing down
>     to vhost, as vhost use this random value to index an array index.
>   - fix the typo in the doc and description
>   - address vq index for reset_owner
>
> Changes since v1:
>   - use s->nc.info_str when bringing up/down the backend
>
>   docs/specs/vhost-user.txt |  5 +++++
>   hw/net/vhost_net.c        |  3 ++-
>   hw/virtio/vhost-user.c    | 11 ++++++++++-
>   net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>   qapi-schema.json          |  6 +++++-
>   qemu-options.hx           |  5 +++--
>   6 files changed, 49 insertions(+), 18 deletions(-)
>
> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> index 650bb18..2c8e934 100644
> --- a/docs/specs/vhost-user.txt
> +++ b/docs/specs/vhost-user.txt
> @@ -127,6 +127,11 @@ in the ancillary data:
>   If Master is unable to send the full message or receives a wrong reply it will
>   close the connection. An optional reconnection mechanism can be implemented.
>
> +Multi queue support
> +-------------------
> +The protocol supports multiple queues by setting all index fields in the sent
> +messages to a properly calculated value.
> +
>   Message types
>   -------------
>
> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> index 47f8b89..426b23e 100644
> --- a/hw/net/vhost_net.c
> +++ b/hw/net/vhost_net.c
> @@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
>
>       net->dev.nvqs = 2;
>       net->dev.vqs = net->vqs;
> +    net->dev.vq_index = net->nc->queue_index;
>
>       r = vhost_dev_init(&net->dev, options->opaque,
>                          options->backend_type, options->force);
> @@ -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
>           for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
>               const VhostOps *vhost_ops = net->dev.vhost_ops;
>               int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> -                                          NULL);
> +                                          &file);
>               assert(r >= 0);
>           }
>       }
> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> index e7ab829..d6f2163 100644
> --- a/hw/virtio/vhost-user.c
> +++ b/hw/virtio/vhost-user.c
> @@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>           break;
>
>       case VHOST_SET_OWNER:
> +        break;
> +
>       case VHOST_RESET_OWNER:
> +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
> +        msg.size = sizeof(m.state);
>           break;
>
>       case VHOST_SET_MEM_TABLE:
> @@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>       case VHOST_SET_VRING_NUM:
>       case VHOST_SET_VRING_BASE:
>           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
>           msg.size = sizeof(m.state);
>           break;
>
>       case VHOST_GET_VRING_BASE:
>           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> +        msg.state.index += dev->vq_index;
>           msg.size = sizeof(m.state);
>           need_reply = 1;
>           break;
>
>       case VHOST_SET_VRING_ADDR:
>           memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> +        msg.addr.index += dev->vq_index;
>           msg.size = sizeof(m.addr);
>           break;
>
> @@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>       case VHOST_SET_VRING_CALL:
>       case VHOST_SET_VRING_ERR:
>           file = arg;
> -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> +        msg.u64 = (file->index + dev->vq_index) & VHOST_USER_VRING_IDX_MASK;
>           msg.size = sizeof(m.u64);
>           if (ioeventfd_enabled() && file->fd > 0) {
>               fds[fd_num++] = file->fd;
> @@ -313,6 +321,7 @@ static int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>                   error_report("Received bad msg size.");
>                   return -1;
>               }
> +            msg.state.index -= dev->vq_index;
>               memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
>               break;
>           default:
> diff --git a/net/vhost-user.c b/net/vhost-user.c
> index 1d86a2b..904d8af 100644
> --- a/net/vhost-user.c
> +++ b/net/vhost-user.c
> @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque, int event)
>       case CHR_EVENT_OPENED:
>           vhost_user_start(s);
>           net_vhost_link_down(s, false);
> -        error_report("chardev \"%s\" went up", s->chr->label);
> +        error_report("chardev \"%s\" went up", s->nc.info_str);
>           break;
>       case CHR_EVENT_CLOSED:
>           net_vhost_link_down(s, true);
>           vhost_user_stop(s);
> -        error_report("chardev \"%s\" went down", s->chr->label);
> +        error_report("chardev \"%s\" went down", s->nc.info_str);
>           break;
>       }
>   }
>
>   static int net_vhost_user_init(NetClientState *peer, const char *device,
> -                               const char *name, CharDriverState *chr)
> +                               const char *name, CharDriverState *chr,
> +                               uint32_t queues)
>   {
>       NetClientState *nc;
>       VhostUserState *s;
> +    int i;
>
> -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> +    for (i = 0; i < queues; i++) {
> +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
>
> -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> -             chr->label);
> +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> +                 i, chr->label);
>
> -    s = DO_UPCAST(VhostUserState, nc, nc);
> +        s = DO_UPCAST(VhostUserState, nc, nc);
>
> -    /* We don't provide a receive callback */
> -    s->nc.receive_disabled = 1;
> -    s->chr = chr;
> -
> -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> +        /* We don't provide a receive callback */
> +        s->nc.receive_disabled = 1;
> +        s->chr = chr;
> +        s->nc.queue_index = i;
>
> +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> +    }
>       return 0;
>   }
>
> @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
>   int net_init_vhost_user(const NetClientOptions *opts, const char *name,
>                           NetClientState *peer)
>   {
> +    uint32_t queues;
>       const NetdevVhostUserOptions *vhost_user_opts;
>       CharDriverState *chr;
>
> @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
>           return -1;
>       }
>
> +    /* number of queues for multiqueue */
> +    if (vhost_user_opts->has_queues) {
> +        queues = vhost_user_opts->queues;
> +    } else {
> +        queues = 1;
> +    }
>
> -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
>   }
> diff --git a/qapi-schema.json b/qapi-schema.json
> index f97ffa1..00791dd 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2444,12 +2444,16 @@
>   #
>   # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
>   #
> +# @queues: #optional number of queues to be created for multiqueue vhost-user
> +#          (default: 1) (Since 2.4)
> +#
>   # Since 2.1
>   ##
>   { 'struct': 'NetdevVhostUserOptions',
>     'data': {
>       'chardev':        'str',
> -    '*vhostforce':    'bool' } }
> +    '*vhostforce':    'bool',
> +    '*queues':        'uint32' } }
>
>   ##
>   # @NetClientOptions
> diff --git a/qemu-options.hx b/qemu-options.hx
> index ec356f6..dad035e 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
>   netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
>   required hub automatically.
>
> -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
>
>   Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
>   be a unix domain socket backed one. The vhost-user uses a specifically defined
>   protocol to pass vhost ioctl replacement messages to an application on the other
>   end of the socket. On non-MSIX guests, the feature can be forced with
> -@var{vhostforce}.
> +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> +be created for multiqueue vhost-user.
>
>   Example:
>   @example
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-08-30 15:28 ` [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Marcel Apfelbaum
@ 2015-08-31  5:28   ` Ouyang, Changchun
  2015-08-31  5:42     ` Xu, Qian Q
  0 siblings, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-08-31  5:28 UTC (permalink / raw)
  To: marcel, qemu-devel, mst, Xu, Qian Q
  Cc: snabb-devel, Liu, Yuanhan, n.nikolaev, luke, Long, Thomas,
	Ouyang, Changchun


> -----Original Message-----
> From: Marcel Apfelbaum [mailto:marcel.apfelbaum@gmail.com]
> Sent: Sunday, August 30, 2015 11:28 PM
> To: Ouyang, Changchun; qemu-devel@nongnu.org; mst@redhat.com
> Cc: snabb-devel@googlegroups.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas
> Subject: Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
> 
> On 05/28/2015 04:23 AM, Ouyang Changchun wrote:
> > Based on patch by Nikolay Nikolaev:
> > Vhost-user will implement the multi queue support in a similar way to
> > what vhost already has - a separate thread for each queue.
> > To enable the multi queue functionality - a new command line parameter
> > "queues" is introduced for the vhost-user netdev.
> >
> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> Hi,
> 
> Can you please share how you did you test it?
> Was it the DPDK vhost-user example? (after the MQ patches, of course) I ask
> because I tried to test it with no success so far.
> Any pointers would be appreciated.
> 

Yes, I use DPDK vhost-user example to test it.
Hope the following link help you a bit.
http://article.gmane.org/gmane.comp.networking.dpdk.devel/22758/match=vhost+multiple

Qian and Yuanhan, maybe you can have more try and share more information here. 

Thanks
Changchun

> Thanks,
> Marcel
> 
> 
> > ---
> > Changes since v4:
> >   - remove the unnecessary trailing '\n'
> >
> > Changes since v3:
> >   - fix one typo and wrap one long line
> >
> > Changes since v2:
> >   - fix vq index issue for set_vring_call
> >     When it is the case of VHOST_SET_VRING_CALL, The vq_index is not
> initialized before it is used,
> >     thus it could be a random value. The random value leads to crash in vhost
> after passing down
> >     to vhost, as vhost use this random value to index an array index.
> >   - fix the typo in the doc and description
> >   - address vq index for reset_owner
> >
> > Changes since v1:
> >   - use s->nc.info_str when bringing up/down the backend
> >
> >   docs/specs/vhost-user.txt |  5 +++++
> >   hw/net/vhost_net.c        |  3 ++-
> >   hw/virtio/vhost-user.c    | 11 ++++++++++-
> >   net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> >   qapi-schema.json          |  6 +++++-
> >   qemu-options.hx           |  5 +++--
> >   6 files changed, 49 insertions(+), 18 deletions(-)
> >
> > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > index 650bb18..2c8e934 100644
> > --- a/docs/specs/vhost-user.txt
> > +++ b/docs/specs/vhost-user.txt
> > @@ -127,6 +127,11 @@ in the ancillary data:
> >   If Master is unable to send the full message or receives a wrong reply it
> will
> >   close the connection. An optional reconnection mechanism can be
> implemented.
> >
> > +Multi queue support
> > +-------------------
> > +The protocol supports multiple queues by setting all index fields in
> > +the sent messages to a properly calculated value.
> > +
> >   Message types
> >   -------------
> >
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > 47f8b89..426b23e 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
> > *options)
> >
> >       net->dev.nvqs = 2;
> >       net->dev.vqs = net->vqs;
> > +    net->dev.vq_index = net->nc->queue_index;
> >
> >       r = vhost_dev_init(&net->dev, options->opaque,
> >                          options->backend_type, options->force); @@
> > -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
> >           for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> >               const VhostOps *vhost_ops = net->dev.vhost_ops;
> >               int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > -                                          NULL);
> > +                                          &file);
> >               assert(r >= 0);
> >           }
> >       }
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > e7ab829..d6f2163 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >           break;
> >
> >       case VHOST_SET_OWNER:
> > +        break;
> > +
> >       case VHOST_RESET_OWNER:
> > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> > +        msg.size = sizeof(m.state);
> >           break;
> >
> >       case VHOST_SET_MEM_TABLE:
> > @@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >       case VHOST_SET_VRING_NUM:
> >       case VHOST_SET_VRING_BASE:
> >           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >           msg.size = sizeof(m.state);
> >           break;
> >
> >       case VHOST_GET_VRING_BASE:
> >           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >           msg.size = sizeof(m.state);
> >           need_reply = 1;
> >           break;
> >
> >       case VHOST_SET_VRING_ADDR:
> >           memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > +        msg.addr.index += dev->vq_index;
> >           msg.size = sizeof(m.addr);
> >           break;
> >
> > @@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev *dev,
> unsigned long int request,
> >       case VHOST_SET_VRING_CALL:
> >       case VHOST_SET_VRING_ERR:
> >           file = arg;
> > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > +        msg.u64 = (file->index + dev->vq_index) &
> > + VHOST_USER_VRING_IDX_MASK;
> >           msg.size = sizeof(m.u64);
> >           if (ioeventfd_enabled() && file->fd > 0) {
> >               fds[fd_num++] = file->fd; @@ -313,6 +321,7 @@ static int
> > vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> >                   error_report("Received bad msg size.");
> >                   return -1;
> >               }
> > +            msg.state.index -= dev->vq_index;
> >               memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> >               break;
> >           default:
> > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > 1d86a2b..904d8af 100644
> > --- a/net/vhost-user.c
> > +++ b/net/vhost-user.c
> > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque,
> int event)
> >       case CHR_EVENT_OPENED:
> >           vhost_user_start(s);
> >           net_vhost_link_down(s, false);
> > -        error_report("chardev \"%s\" went up", s->chr->label);
> > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> >           break;
> >       case CHR_EVENT_CLOSED:
> >           net_vhost_link_down(s, true);
> >           vhost_user_stop(s);
> > -        error_report("chardev \"%s\" went down", s->chr->label);
> > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> >           break;
> >       }
> >   }
> >
> >   static int net_vhost_user_init(NetClientState *peer, const char *device,
> > -                               const char *name, CharDriverState *chr)
> > +                               const char *name, CharDriverState *chr,
> > +                               uint32_t queues)
> >   {
> >       NetClientState *nc;
> >       VhostUserState *s;
> > +    int i;
> >
> > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> name);
> > +    for (i = 0; i < queues; i++) {
> > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > + name);
> >
> > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > -             chr->label);
> > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > +                 i, chr->label);
> >
> > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > +        s = DO_UPCAST(VhostUserState, nc, nc);
> >
> > -    /* We don't provide a receive callback */
> > -    s->nc.receive_disabled = 1;
> > -    s->chr = chr;
> > -
> > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> s);
> > +        /* We don't provide a receive callback */
> > +        s->nc.receive_disabled = 1;
> > +        s->chr = chr;
> > +        s->nc.queue_index = i;
> >
> > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> s);
> > +    }
> >       return 0;
> >   }
> >
> > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts,
> void *opaque)
> >   int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> >                           NetClientState *peer)
> >   {
> > +    uint32_t queues;
> >       const NetdevVhostUserOptions *vhost_user_opts;
> >       CharDriverState *chr;
> >
> > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions
> *opts, const char *name,
> >           return -1;
> >       }
> >
> > +    /* number of queues for multiqueue */
> > +    if (vhost_user_opts->has_queues) {
> > +        queues = vhost_user_opts->queues;
> > +    } else {
> > +        queues = 1;
> > +    }
> >
> > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > + queues);
> >   }
> > diff --git a/qapi-schema.json b/qapi-schema.json index
> > f97ffa1..00791dd 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -2444,12 +2444,16 @@
> >   #
> >   # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> false).
> >   #
> > +# @queues: #optional number of queues to be created for multiqueue
> vhost-user
> > +#          (default: 1) (Since 2.4)
> > +#
> >   # Since 2.1
> >   ##
> >   { 'struct': 'NetdevVhostUserOptions',
> >     'data': {
> >       'chardev':        'str',
> > -    '*vhostforce':    'bool' } }
> > +    '*vhostforce':    'bool',
> > +    '*queues':        'uint32' } }
> >
> >   ##
> >   # @NetClientOptions
> > diff --git a/qemu-options.hx b/qemu-options.hx index ec356f6..dad035e
> > 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a
> QEMU "vlan" instead of a single
> >   netdev.  @code{-net} and @code{-device} with parameter @option{vlan}
> create the
> >   required hub automatically.
> >
> > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > +@item -netdev
> > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> >
> >   Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev
> should
> >   be a unix domain socket backed one. The vhost-user uses a specifically
> defined
> >   protocol to pass vhost ioctl replacement messages to an application on the
> other
> >   end of the socket. On non-MSIX guests, the feature can be forced
> > with -@var{vhostforce}.
> > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
> > +queues to be created for multiqueue vhost-user.
> >
> >   Example:
> >   @example
> >

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-08-31  5:28   ` Ouyang, Changchun
@ 2015-08-31  5:42     ` Xu, Qian Q
  2015-08-31  8:55       ` Marcel Apfelbaum
  0 siblings, 1 reply; 44+ messages in thread
From: Xu, Qian Q @ 2015-08-31  5:42 UTC (permalink / raw)
  To: Ouyang, Changchun, marcel, qemu-devel, mst
  Cc: snabb-devel, Liu, Yuanhan, n.nikolaev, luke, Long, Thomas, Fu, JingguoX

[-- Attachment #1: Type: text/plain, Size: 12198 bytes --]

+ Jingguo, and he will be working on the vhost multi-queue support functional tests. 

Marcel, 
What you try to is to run dpdk-vhost sample and the dpdk-virtio(virtio-pmd) case? Attached the step-by-step guide of running it with one queue, you can update the multiple queue commands in it. 

Thanks
Qian

-----Original Message-----
From: Ouyang, Changchun 
Sent: Monday, August 31, 2015 1:29 PM
To: marcel@redhat.com; qemu-devel@nongnu.org; mst@redhat.com; Xu, Qian Q
Cc: snabb-devel@googlegroups.com; n.nikolaev@virtualopensystems.com; luke@snabb.co; Long, Thomas; Liu, Yuanhan; Ouyang, Changchun
Subject: RE: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support


> -----Original Message-----
> From: Marcel Apfelbaum [mailto:marcel.apfelbaum@gmail.com]
> Sent: Sunday, August 30, 2015 11:28 PM
> To: Ouyang, Changchun; qemu-devel@nongnu.org; mst@redhat.com
> Cc: snabb-devel@googlegroups.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas
> Subject: Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue 
> support
> 
> On 05/28/2015 04:23 AM, Ouyang Changchun wrote:
> > Based on patch by Nikolay Nikolaev:
> > Vhost-user will implement the multi queue support in a similar way 
> > to what vhost already has - a separate thread for each queue.
> > To enable the multi queue functionality - a new command line 
> > parameter "queues" is introduced for the vhost-user netdev.
> >
> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> Hi,
> 
> Can you please share how you did you test it?
> Was it the DPDK vhost-user example? (after the MQ patches, of course) 
> I ask because I tried to test it with no success so far.
> Any pointers would be appreciated.
> 

Yes, I use DPDK vhost-user example to test it.
Hope the following link help you a bit.
http://article.gmane.org/gmane.comp.networking.dpdk.devel/22758/match=vhost+multiple

Qian and Yuanhan, maybe you can have more try and share more information here. 

Thanks
Changchun

> Thanks,
> Marcel
> 
> 
> > ---
> > Changes since v4:
> >   - remove the unnecessary trailing '\n'
> >
> > Changes since v3:
> >   - fix one typo and wrap one long line
> >
> > Changes since v2:
> >   - fix vq index issue for set_vring_call
> >     When it is the case of VHOST_SET_VRING_CALL, The vq_index is not
> initialized before it is used,
> >     thus it could be a random value. The random value leads to crash 
> > in vhost
> after passing down
> >     to vhost, as vhost use this random value to index an array index.
> >   - fix the typo in the doc and description
> >   - address vq index for reset_owner
> >
> > Changes since v1:
> >   - use s->nc.info_str when bringing up/down the backend
> >
> >   docs/specs/vhost-user.txt |  5 +++++
> >   hw/net/vhost_net.c        |  3 ++-
> >   hw/virtio/vhost-user.c    | 11 ++++++++++-
> >   net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> >   qapi-schema.json          |  6 +++++-
> >   qemu-options.hx           |  5 +++--
> >   6 files changed, 49 insertions(+), 18 deletions(-)
> >
> > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt 
> > index 650bb18..2c8e934 100644
> > --- a/docs/specs/vhost-user.txt
> > +++ b/docs/specs/vhost-user.txt
> > @@ -127,6 +127,11 @@ in the ancillary data:
> >   If Master is unable to send the full message or receives a wrong 
> > reply it
> will
> >   close the connection. An optional reconnection mechanism can be
> implemented.
> >
> > +Multi queue support
> > +-------------------
> > +The protocol supports multiple queues by setting all index fields 
> > +in the sent messages to a properly calculated value.
> > +
> >   Message types
> >   -------------
> >
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 
> > 47f8b89..426b23e 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
> > *options)
> >
> >       net->dev.nvqs = 2;
> >       net->dev.vqs = net->vqs;
> > +    net->dev.vq_index = net->nc->queue_index;
> >
> >       r = vhost_dev_init(&net->dev, options->opaque,
> >                          options->backend_type, options->force); @@
> > -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
> >           for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> >               const VhostOps *vhost_ops = net->dev.vhost_ops;
> >               int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
> > -                                          NULL);
> > +                                          &file);
> >               assert(r >= 0);
> >           }
> >       }
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
> > e7ab829..d6f2163 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev 
> > *dev,
> unsigned long int request,
> >           break;
> >
> >       case VHOST_SET_OWNER:
> > +        break;
> > +
> >       case VHOST_RESET_OWNER:
> > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> > +        msg.size = sizeof(m.state);
> >           break;
> >
> >       case VHOST_SET_MEM_TABLE:
> > @@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev 
> > *dev,
> unsigned long int request,
> >       case VHOST_SET_VRING_NUM:
> >       case VHOST_SET_VRING_BASE:
> >           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >           msg.size = sizeof(m.state);
> >           break;
> >
> >       case VHOST_GET_VRING_BASE:
> >           memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > +        msg.state.index += dev->vq_index;
> >           msg.size = sizeof(m.state);
> >           need_reply = 1;
> >           break;
> >
> >       case VHOST_SET_VRING_ADDR:
> >           memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
> > +        msg.addr.index += dev->vq_index;
> >           msg.size = sizeof(m.addr);
> >           break;
> >
> > @@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev 
> > *dev,
> unsigned long int request,
> >       case VHOST_SET_VRING_CALL:
> >       case VHOST_SET_VRING_ERR:
> >           file = arg;
> > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > +        msg.u64 = (file->index + dev->vq_index) & 
> > + VHOST_USER_VRING_IDX_MASK;
> >           msg.size = sizeof(m.u64);
> >           if (ioeventfd_enabled() && file->fd > 0) {
> >               fds[fd_num++] = file->fd; @@ -313,6 +321,7 @@ static 
> > int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
> >                   error_report("Received bad msg size.");
> >                   return -1;
> >               }
> > +            msg.state.index -= dev->vq_index;
> >               memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> >               break;
> >           default:
> > diff --git a/net/vhost-user.c b/net/vhost-user.c index 
> > 1d86a2b..904d8af 100644
> > --- a/net/vhost-user.c
> > +++ b/net/vhost-user.c
> > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque,
> int event)
> >       case CHR_EVENT_OPENED:
> >           vhost_user_start(s);
> >           net_vhost_link_down(s, false);
> > -        error_report("chardev \"%s\" went up", s->chr->label);
> > +        error_report("chardev \"%s\" went up", s->nc.info_str);
> >           break;
> >       case CHR_EVENT_CLOSED:
> >           net_vhost_link_down(s, true);
> >           vhost_user_stop(s);
> > -        error_report("chardev \"%s\" went down", s->chr->label);
> > +        error_report("chardev \"%s\" went down", s->nc.info_str);
> >           break;
> >       }
> >   }
> >
> >   static int net_vhost_user_init(NetClientState *peer, const char *device,
> > -                               const char *name, CharDriverState *chr)
> > +                               const char *name, CharDriverState *chr,
> > +                               uint32_t queues)
> >   {
> >       NetClientState *nc;
> >       VhostUserState *s;
> > +    int i;
> >
> > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> name);
> > +    for (i = 0; i < queues; i++) {
> > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, 
> > + device, name);
> >
> > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > -             chr->label);
> > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > +                 i, chr->label);
> >
> > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > +        s = DO_UPCAST(VhostUserState, nc, nc);
> >
> > -    /* We don't provide a receive callback */
> > -    s->nc.receive_disabled = 1;
> > -    s->chr = chr;
> > -
> > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
> s);
> > +        /* We don't provide a receive callback */
> > +        s->nc.receive_disabled = 1;
> > +        s->chr = chr;
> > +        s->nc.queue_index = i;
> >
> > +        qemu_chr_add_handlers(s->chr, NULL, NULL, 
> > + net_vhost_user_event,
> s);
> > +    }
> >       return 0;
> >   }
> >
> > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts,
> void *opaque)
> >   int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> >                           NetClientState *peer)
> >   {
> > +    uint32_t queues;
> >       const NetdevVhostUserOptions *vhost_user_opts;
> >       CharDriverState *chr;
> >
> > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions
> *opts, const char *name,
> >           return -1;
> >       }
> >
> > +    /* number of queues for multiqueue */
> > +    if (vhost_user_opts->has_queues) {
> > +        queues = vhost_user_opts->queues;
> > +    } else {
> > +        queues = 1;
> > +    }
> >
> > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > +    return net_vhost_user_init(peer, "vhost_user", name, chr, 
> > + queues);
> >   }
> > diff --git a/qapi-schema.json b/qapi-schema.json index 
> > f97ffa1..00791dd 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -2444,12 +2444,16 @@
> >   #
> >   # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
> false).
> >   #
> > +# @queues: #optional number of queues to be created for multiqueue
> vhost-user
> > +#          (default: 1) (Since 2.4)
> > +#
> >   # Since 2.1
> >   ##
> >   { 'struct': 'NetdevVhostUserOptions',
> >     'data': {
> >       'chardev':        'str',
> > -    '*vhostforce':    'bool' } }
> > +    '*vhostforce':    'bool',
> > +    '*queues':        'uint32' } }
> >
> >   ##
> >   # @NetClientOptions
> > diff --git a/qemu-options.hx b/qemu-options.hx index 
> > ec356f6..dad035e
> > 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to 
> > a
> QEMU "vlan" instead of a single
> >   netdev.  @code{-net} and @code{-device} with parameter 
> > @option{vlan}
> create the
> >   required hub automatically.
> >
> > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > +@item -netdev
> > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> >
> >   Establish a vhost-user netdev, backed by a chardev @var{id}. The 
> > chardev
> should
> >   be a unix domain socket backed one. The vhost-user uses a 
> > specifically
> defined
> >   protocol to pass vhost ioctl replacement messages to an 
> > application on the
> other
> >   end of the socket. On non-MSIX guests, the feature can be forced 
> > with -@var{vhostforce}.
> > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of 
> > +queues to be created for multiqueue vhost-user.
> >
> >   Example:
> >   @example
> >


[-- Attachment #2: Vhost-GSG.docx --]
[-- Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document, Size: 238103 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-30  6:16             ` Michael S. Tsirkin
@ 2015-08-31  8:29               ` Ouyang, Changchun
  2015-08-31 11:30                 ` Michael S. Tsirkin
  0 siblings, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-08-31  8:29 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, Liu, Yuanhan, thibaut.collet, qemu-devel,
	n.nikolaev, luke, Long, Thomas, Ouyang, Changchun



> -----Original Message-----
> From: Michael S. Tsirkin [mailto:mst@redhat.com]
> Sent: Sunday, August 30, 2015 2:16 PM
> To: Ouyang, Changchun
> Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> luke@snabb.co; Long, Thomas; Liu, Yuanhan
> Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> support
> 
> On Fri, Aug 28, 2015 at 01:53:39AM +0000, Ouyang, Changchun wrote:
> > Hi Michael,
> >
> > Thanks for your response!
> >
> > > -----Original Message-----
> > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > Sent: Thursday, August 27, 2015 9:05 PM
> > > To: Ouyang, Changchun
> > > Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > luke@snabb.co; Long, Thomas; Liu, Yuanhan
> > > Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > queue support
> > >
> > > On Tue, Aug 25, 2015 at 03:25:54AM +0000, Ouyang, Changchun wrote:
> > > > Hi Michael,
> > > >
> > > > > -----Original Message-----
> > > > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > > > Sent: Thursday, August 13, 2015 5:19 PM
> > > > > To: Ouyang, Changchun
> > > > > Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> > > > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > > > luke@snabb.co; Long, Thomas
> > > > > Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > > > queue support
> > > > >
> > > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > > Based on patch by Nikolay Nikolaev:
> > > > > > Vhost-user will implement the multi queue support in a similar
> > > > > > way to what vhost already has - a separate thread for each queue.
> > > > > > To enable the multi queue functionality - a new command line
> > > > > > parameter "queues" is introduced for the vhost-user netdev.
> > > > > >
> > > > > > The RESET_OWNER change is based on commit:
> > > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > > If it is reverted, the patch need update for it accordingly.
> > > > > >
> > > > > > Signed-off-by: Nikolay Nikolaev
> > > > > > <n.nikolaev@virtualopensystems.com>
> > > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > > > ---
> > > > > > Changes since v5:
> > > > > >  - fix the message descption for VHOST_RESET_OWNER in
> > > > > > vhost-user txt
> > > > > >
> > > > > > Changes since v4:
> > > > > >  - remove the unnecessary trailing '\n'
> > > > > >
> > > > > > Changes since v3:
> > > > > >  - fix one typo and wrap one long line
> > > > > >
> > > > > > Changes since v2:
> > > > > >  - fix vq index issue for set_vring_call
> > > > > >    When it is the case of VHOST_SET_VRING_CALL, The vq_index
> > > > > > is not
> > > > > initialized before it is used,
> > > > > >    thus it could be a random value. The random value leads to
> > > > > > crash in vhost
> > > > > after passing down
> > > > > >    to vhost, as vhost use this random value to index an array index.
> > > > > >  - fix the typo in the doc and description
> > > > > >  - address vq index for reset_owner
> > > > > >
> > > > > > Changes since v1:
> > > > > >  - use s->nc.info_str when bringing up/down the backend
> > > > > >
> > > > > >  docs/specs/vhost-user.txt |  7 ++++++-
> > > > > >  hw/net/vhost_net.c        |  3 ++-
> > > > > >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> > > > > >  net/vhost-user.c          | 37 ++++++++++++++++++++++++------------
> -
> > > > > >  qapi-schema.json          |  6 +++++-
> > > > > >  qemu-options.hx           |  5 +++--
> > > > > >  6 files changed, 50 insertions(+), 19 deletions(-)
> > > > > >
> > > > > > diff --git a/docs/specs/vhost-user.txt
> > > > > > b/docs/specs/vhost-user.txt index 70da3b1..9390f89 100644
> > > > > > --- a/docs/specs/vhost-user.txt
> > > > > > +++ b/docs/specs/vhost-user.txt
> > > > > > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > > > > > protocol features,  a feature bit was dedicated for this purpose:
> > > > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > > > >
> > > > > > +Multi queue support
> > > > > > +-------------------
> > > > > > +The protocol supports multiple queues by setting all index
> > > > > > +fields in the sent messages to a properly calculated value.
> > > > > > +
> > > > > >  Message types
> > > > > >  -------------
> > > > > >
> > > > > > @@ -198,7 +203,7 @@ Message types
> > > > > >
> > > > > >        Id: 4
> > > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > > -      Master payload: N/A
> > > > > > +      Master payload: vring state description
> > > > > >
> > > > > >        Issued when a new connection is about to be closed. The
> > > > > > Master
> > > will no
> > > > > >        longer own this connection (and will usually close it).
> > > > >
> > > > > This is an interface change, isn't it?
> > > > > We can't make it unconditionally, need to make it dependent on a
> > > > > protocol flag.
> > >
> > >
> > > Pls remember to fix this one.
> > >
> > > > >
> > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > > > 1f25cb3..9cd6c05 100644
> > > > > > --- a/hw/net/vhost_net.c
> > > > > > +++ b/hw/net/vhost_net.c
> > > > > > @@ -159,6 +159,7 @@ struct vhost_net
> > > > > > *vhost_net_init(VhostNetOptions
> > > > > > *options)
> > > > > >
> > > > > >      net->dev.nvqs = 2;
> > > > > >      net->dev.vqs = net->vqs;
> > > > > > +    net->dev.vq_index = net->nc->queue_index;
> > > > > >
> > > > > >      r = vhost_dev_init(&net->dev, options->opaque,
> > > > > >                         options->backend_type,
> > > > > > options->force); @@
> > > > > > -269,7 +270,7 @@ static void vhost_net_stop_one(struct
> > > > > > vhost_net
> > > *net,
> > > > > >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> > > > > >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > > > >              int r = vhost_ops->vhost_call(&net->dev,
> VHOST_RESET_OWNER,
> > > > > > -                                          NULL);
> > > > > > +                                          &file);
> > > > > >              assert(r >= 0);
> > > > > >          }
> > > > > >      }
> > > > > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> > > > > > index 27ba035..fb11d4c 100644
> > > > > > --- a/hw/virtio/vhost-user.c
> > > > > > +++ b/hw/virtio/vhost-user.c
> > > > > > @@ -219,7 +219,12 @@ static int vhost_user_call(struct
> > > > > > vhost_dev *dev,
> > > > > unsigned long int request,
> > > > > >          break;
> > > > > >
> > > > > >      case VHOST_USER_SET_OWNER:
> > > > > > +        break;
> > > > > > +
> > > > > >      case VHOST_USER_RESET_OWNER:
> > > > > > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > > > > +        msg.state.index += dev->vq_index;
> > > > > > +        msg.size = sizeof(m.state);
> > > > > >          break;
> > > > > >
> > > > > >      case VHOST_USER_SET_MEM_TABLE:
> > > > > > @@ -262,17 +267,20 @@ static int vhost_user_call(struct
> > > > > > vhost_dev *dev,
> > > > > unsigned long int request,
> > > > > >      case VHOST_USER_SET_VRING_NUM:
> > > > > >      case VHOST_USER_SET_VRING_BASE:
> > > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > > vhost_vring_state));
> > > > > > +        msg.state.index += dev->vq_index;
> > > > > >          msg.size = sizeof(m.state);
> > > > > >          break;
> > > > > >
> > > > > >      case VHOST_USER_GET_VRING_BASE:
> > > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > > vhost_vring_state));
> > > > > > +        msg.state.index += dev->vq_index;
> > > > > >          msg.size = sizeof(m.state);
> > > > > >          need_reply = 1;
> > > > > >          break;
> > > > > >
> > > > > >      case VHOST_USER_SET_VRING_ADDR:
> > > > > >          memcpy(&msg.addr, arg, sizeof(struct
> > > > > > vhost_vring_addr));
> > > > > > +        msg.addr.index += dev->vq_index;
> > > > > >          msg.size = sizeof(m.addr);
> > > > > >          break;
> > > > > >
> > > > > > @@ -280,7 +288,7 @@ static int vhost_user_call(struct
> > > > > > vhost_dev *dev,
> > > > > unsigned long int request,
> > > > > >      case VHOST_USER_SET_VRING_CALL:
> > > > > >      case VHOST_USER_SET_VRING_ERR:
> > > > > >          file = arg;
> > > > > > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > > > > > +        msg.u64 = (file->index + dev->vq_index) &
> > > > > > + VHOST_USER_VRING_IDX_MASK;
> > > > > >          msg.size = sizeof(m.u64);
> > > > > >          if (ioeventfd_enabled() && file->fd > 0) {
> > > > > >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@
> > > > > > static int vhost_user_call(struct vhost_dev *dev, unsigned long int
> request,
> > > > > >                  error_report("Received bad msg size.");
> > > > > >                  return -1;
> > > > > >              }
> > > > > > +            msg.state.index -= dev->vq_index;
> > > > > >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> > > > > >              break;
> > > > > >          default:
> > > > > > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > > > > > 1d86a2b..904d8af 100644
> > > > > > --- a/net/vhost-user.c
> > > > > > +++ b/net/vhost-user.c
> > > > > > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void
> > > > > > *opaque,
> > > > > int event)
> > > > > >      case CHR_EVENT_OPENED:
> > > > > >          vhost_user_start(s);
> > > > > >          net_vhost_link_down(s, false);
> > > > > > -        error_report("chardev \"%s\" went up", s->chr->label);
> > > > > > +        error_report("chardev \"%s\" went up",
> > > > > > + s->nc.info_str);
> > > > > >          break;
> > > > > >      case CHR_EVENT_CLOSED:
> > > > > >          net_vhost_link_down(s, true);
> > > > > >          vhost_user_stop(s);
> > > > > > -        error_report("chardev \"%s\" went down", s->chr->label);
> > > > > > +        error_report("chardev \"%s\" went down",
> > > > > > + s->nc.info_str);
> > > > > >          break;
> > > > > >      }
> > > > > >  }
> > >
> > > BTW this seems pretty hacky: you get multiple messages when one
> > > client connects. Why add multiple event listeners to the same chat device?
> > >
> > >
> > > > > >
> > > > > >  static int net_vhost_user_init(NetClientState *peer, const char
> *device,
> > > > > > -                               const char *name, CharDriverState *chr)
> > > > > > +                               const char *name, CharDriverState *chr,
> > > > > > +                               uint32_t queues)
> > > > > >  {
> > > > > >      NetClientState *nc;
> > > > > >      VhostUserState *s;
> > > > > > +    int i;
> > > > > >
> > > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > > > > name);
> > > > > > +    for (i = 0; i < queues; i++) {
> > > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > > > + device, name);
> > > > > >
> > > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > > -             chr->label);
> > > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d
> to %s",
> > > > > > +                 i, chr->label);
> > > > > >
> > > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > >
> > > > > > -    /* We don't provide a receive callback */
> > > > > > -    s->nc.receive_disabled = 1;
> > > > > > -    s->chr = chr;
> > > > > > -
> > > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > net_vhost_user_event,
> > > > > s);
> > > > > > +        /* We don't provide a receive callback */
> > > > > > +        s->nc.receive_disabled = 1;
> > > > > > +        s->chr = chr;
> > > > > > +        s->nc.queue_index = i;
> > > > > >
> > > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > > > > + net_vhost_user_event,
> > > > > s);
> > > > > > +    }
> > > > > >      return 0;
> > > > > >  }
> > > > > >
> > > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> > > *opts,
> > > > > > void *opaque)
> > > > >
> > > > >
> > > > > There are two problems here:
> > > > >
> > > > > 1. we don't really know that the backend
> > > > >    is able to support the requested number of queues.
> > > > >    If not, everything will fail, silently.
> > > > >    A new message to query the # of queues could help, though
> > > > >    I'm not sure what can be done on failure. Fail connection?
> > > > >
> > > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > > >    on the same socket.
> > > > >
> > > > I think it is tough to resolve these 2 comments, as the current
> > > > message is either vhost-dev based or virt-queue based, The
> > > > multiple
> > > queues(pair) feature use multiple vhost-devs to implement itself.
> > > > For #1
> > > > So the queue number is something should be seen in the upper level
> > > > of
> > > vhost-dev rather than inside the vhost-dev.
> > > > For each vhost-net, there are 2 virt-queues, one is for Rx the other is
> for Tx.
> > > > introduce the virt-queue pair number into the vhost-dev? But I
> > > > don't think it is good, as for each vhost-dev, there is only one virt-
> queue pair.
> > > >
> > > > Where should I put the virt-queue pair number to? I don't get the
> > > > perfect
> > > answer till now. Any suggestion is welcome.
> > > >
> > > > Could we assume the vhost backend has the ability to create enough
> > > > virt-queue pair(e.g. 0x8000 is the max) if qemu require Vhost
> > > > backend to do it. If it is correct, we don't need get virt-queue
> > > > pair number from
> > > vhost backend, as vhost backend can Create all virt-queue pair
> > > required by qemu.
> > > > The virtio frontend(on guest) has the flexibility to enable which
> > > > virt-queue
> > > according to its own capability, qemu can do it by using
> > > > Set_vring_flag message to notify vhost backend.
> > >
> > > I'm reluctant to agree to this. Implementations tend to get this wrong, e.g.
> > > they would only test with 2 queues and assume everything is OK.
> > > With an explicit message, this seems more robust.
> > >
> > > Why is it so hard to implement?  User specifies queues=X.
> > > Can't we simply validate that backend supports this # of queues?
> >
> > Yes exactly in the qemu, we use qeueus=X to specify the virt-queue pair
> number.
> > In my previous comments, I am talking about how to resolve such scenario:
> > vhost backend specify the queues=Y(Y != X, e.g. X = 8, Y = 4), how
> > vhost backend tell qemu that it only has the capability of max
> > virt-queue pair is 4, and qemu need update its max queue number
> according to its own parameter and the max value from vhost back end.
> >
> > Do you think whether this scenario makes sense or not?
> 
> No, I think that if we can't support the number requested by user, QEMU can
> simply exit.

Well, both values are input from user, for some unknown reason, they are different.
When startup the vhost backend, user specify 4 queues, like:
Vhost-user ...  -queues 4      # Y=4
When startup the guest, user specify 8 queues, like:
Qemu-kvm ... -queues 8      # X=8

Vhost backend can't support the queues number as much as the guest/qemu requires,
I think you mean we should let qemu exit in such a case, right?   

Then how about the other case:
When startup the vhost backend, user specify 8 queues, like:
Vhost-user ...  -queues 8      # Y=8
When startup the guest, user specify 4 queues, like:
Qemu-kvm ... -queues 4      # X=4

Vhost backend CAN support the queues number as much as the guest/qemu requires,
And qemu don't want enable all of them(8 in the case), just part of them(only 4 from 8).
Will qemu exit or go forward(of course with 4 queues)? 

> 
> > If yes, then we should consider extend new message to allow vhost
> > backend communicate Its virt-queue number to qemu.
> 
> Yes, conditional on the mq protocol flag.
> 
> > More than that, either we need change codes to allow each net_client
> > has more than
> > 1 virt-queue pair(==2 virt-queue, one for Rx, the other for Tx), Or
> > another better solution for that?
> 
> I'm not sure why is that required for the above.
> 
> > >
> > >
> > > > For #2
> > > > The memory table message is also vhost-dev based, it wouldn't hurt
> > > > we send it a few times, vhost backend could Keep it vhost-dev
> > > > based too, or keep it once(keep it when first time and ignore in
> > > > rest messages from the same connected-fd) Any other good
> > > > suggestion is welcome too
> > > > :-)
> > >
> > > Add code in vhost-user to skip sending the useless messages?  Yes
> > > they seem harmless but implementations tend to develop dependencies
> > > on such bugs, then we get to maintain them forever.
> >
> > Considering we use multiple vhost_net(multiple net_client) to fulfill
> multiple virt-queue pairs.
> > So only the first virt-queue pair will send the set-memory-table, others
> won't do it.
> > Is that ok? so apparently each net client will have difference in message
> count.
> > The first net client will have the message of set memory table, others have
> not.
> >
> > Thanks
> > Changchun
> 
> But all these clients use the same unix domain socket, correct?
Yes, correct

> If so, I don't think it matters that internally in qemu they use different net
> clients. From the external point of view, it looks like a single message is sent
> on a single socket.
> 
> > >
> > > > >
> > > > >
> > > > > >  int net_init_vhost_user(const NetClientOptions *opts, const
> > > > > > char
> > > *name,
> > > > > >                          NetClientState *peer)  {
> > > > > > +    uint32_t queues;
> > > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > > >      CharDriverState *chr;
> > > > > >
> > > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> > > > > > NetClientOptions
> > > > > *opts, const char *name,
> > > > > >          return -1;
> > > > > >      }
> > > > > >
> > > > > > +    /* number of queues for multiqueue */
> > > > > > +    if (vhost_user_opts->has_queues) {
> > > > > > +        queues = vhost_user_opts->queues;
> > > > > > +    } else {
> > > > > > +        queues = 1;
> > > > > > +    }
> > > > > >
> > > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > > > + queues);
> > > > > >  }
> > > > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > > > f97ffa1..51e40ce 100644
> > > > > > --- a/qapi-schema.json
> > > > > > +++ b/qapi-schema.json
> > > > > > @@ -2444,12 +2444,16 @@
> > > > > >  #
> > > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests
> (default:
> > > > > false).
> > > > > >  #
> > > > > > +# @queues: #optional number of queues to be created for
> > > > > > +multiqueue
> > > > > vhost-user
> > > > > > +#          (default: 1) (Since 2.5)
> > > > > > +#
> > > > > >  # Since 2.1
> > > > > >  ##
> > > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > > >    'data': {
> > > > > >      'chardev':        'str',
> > > > > > -    '*vhostforce':    'bool' } }
> > > > > > +    '*vhostforce':    'bool',
> > > > > > +    '*queues':        'uint32' } }
> > > > > >
> > > > > >  ##
> > > > > >  # @NetClientOptions
> > > > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > > > ec356f6..dad035e
> > > > > > 100644
> > > > > > --- a/qemu-options.hx
> > > > > > +++ b/qemu-options.hx
> > > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a
> > > > > > NIC to a QEMU "vlan" instead of a single  netdev.  @code{-net}
> > > > > > and @code{-device} with parameter @option{vlan} create the
> > > > > > required hub
> > > > > automatically.
> > > > > >
> > > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > > +@item -netdev
> > > > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > > >
> > > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}.
> > > > > > The chardev should  be a unix domain socket backed one. The
> > > > > > vhost-user uses a specifically defined  protocol to pass vhost
> > > > > > ioctl replacement messages to an application on the other  end
> > > > > > of the socket. On non-MSIX guests, the feature can be forced
> > > > > > with -
> > > @var{vhostforce}.
> > > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number
> > > > > > +of queues to be created for multiqueue vhost-user.
> > > > > >
> > > > > >  Example:
> > > > > >  @example
> > > > > > --
> > > > > > 1.8.4.2
> > > > > >
> > > > >
> > > > > --
> > > > > You received this message because you are subscribed to the
> > > > > Google Groups "Snabb Switch development" group.
> > > > > To unsubscribe from this group and stop receiving emails from
> > > > > it, send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > > > To post to this group, send an email to snabb-
> devel@googlegroups.com.
> > > > > Visit this group at http://groups.google.com/group/snabb-devel.
> > >
> > > --
> > > You received this message because you are subscribed to the Google
> > > Groups "Snabb Switch development" group.
> > > To unsubscribe from this group and stop receiving emails from it,
> > > send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > To post to this group, send an email to snabb-devel@googlegroups.com.
> > > Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
  2015-08-31  5:42     ` Xu, Qian Q
@ 2015-08-31  8:55       ` Marcel Apfelbaum
  0 siblings, 0 replies; 44+ messages in thread
From: Marcel Apfelbaum @ 2015-08-31  8:55 UTC (permalink / raw)
  To: Xu, Qian Q, Ouyang, Changchun, qemu-devel, mst
  Cc: snabb-devel, Liu, Yuanhan, n.nikolaev, luke, Long, Thomas, Fu, JingguoX

On 08/31/2015 08:42 AM, Xu, Qian Q wrote:
> + Jingguo, and he will be working on the vhost multi-queue support functional tests.
>
> Marcel,
> What you try to is to run dpdk-vhost sample and the dpdk-virtio(virtio-pmd) case? Attached the step-by-step guide of running it with one queue, you can update the multiple queue commands in it.
>

Yes. Thanks a lot for the information!
I'll give it a try,
Marcel

> Thanks
> Qian
>
> -----Original Message-----
> From: Ouyang, Changchun
> Sent: Monday, August 31, 2015 1:29 PM
> To: marcel@redhat.com; qemu-devel@nongnu.org; mst@redhat.com; Xu, Qian Q
> Cc: snabb-devel@googlegroups.com; n.nikolaev@virtualopensystems.com; luke@snabb.co; Long, Thomas; Liu, Yuanhan; Ouyang, Changchun
> Subject: RE: [Qemu-devel] [PATCH v5] vhost-user: add multi queue support
>
>
>> -----Original Message-----
>> From: Marcel Apfelbaum [mailto:marcel.apfelbaum@gmail.com]
>> Sent: Sunday, August 30, 2015 11:28 PM
>> To: Ouyang, Changchun; qemu-devel@nongnu.org; mst@redhat.com
>> Cc: snabb-devel@googlegroups.com; n.nikolaev@virtualopensystems.com;
>> luke@snabb.co; Long, Thomas
>> Subject: Re: [Qemu-devel] [PATCH v5] vhost-user: add multi queue
>> support
>>
>> On 05/28/2015 04:23 AM, Ouyang Changchun wrote:
>>> Based on patch by Nikolay Nikolaev:
>>> Vhost-user will implement the multi queue support in a similar way
>>> to what vhost already has - a separate thread for each queue.
>>> To enable the multi queue functionality - a new command line
>>> parameter "queues" is introduced for the vhost-user netdev.
>>>
>>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>> Hi,
>>
>> Can you please share how you did you test it?
>> Was it the DPDK vhost-user example? (after the MQ patches, of course)
>> I ask because I tried to test it with no success so far.
>> Any pointers would be appreciated.
>>
>
> Yes, I use DPDK vhost-user example to test it.
> Hope the following link help you a bit.
> http://article.gmane.org/gmane.comp.networking.dpdk.devel/22758/match=vhost+multiple
>
> Qian and Yuanhan, maybe you can have more try and share more information here.
>
> Thanks
> Changchun
>
>> Thanks,
>> Marcel
>>
>>
>>> ---
>>> Changes since v4:
>>>    - remove the unnecessary trailing '\n'
>>>
>>> Changes since v3:
>>>    - fix one typo and wrap one long line
>>>
>>> Changes since v2:
>>>    - fix vq index issue for set_vring_call
>>>      When it is the case of VHOST_SET_VRING_CALL, The vq_index is not
>> initialized before it is used,
>>>      thus it could be a random value. The random value leads to crash
>>> in vhost
>> after passing down
>>>      to vhost, as vhost use this random value to index an array index.
>>>    - fix the typo in the doc and description
>>>    - address vq index for reset_owner
>>>
>>> Changes since v1:
>>>    - use s->nc.info_str when bringing up/down the backend
>>>
>>>    docs/specs/vhost-user.txt |  5 +++++
>>>    hw/net/vhost_net.c        |  3 ++-
>>>    hw/virtio/vhost-user.c    | 11 ++++++++++-
>>>    net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>>>    qapi-schema.json          |  6 +++++-
>>>    qemu-options.hx           |  5 +++--
>>>    6 files changed, 49 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
>>> index 650bb18..2c8e934 100644
>>> --- a/docs/specs/vhost-user.txt
>>> +++ b/docs/specs/vhost-user.txt
>>> @@ -127,6 +127,11 @@ in the ancillary data:
>>>    If Master is unable to send the full message or receives a wrong
>>> reply it
>> will
>>>    close the connection. An optional reconnection mechanism can be
>> implemented.
>>>
>>> +Multi queue support
>>> +-------------------
>>> +The protocol supports multiple queues by setting all index fields
>>> +in the sent messages to a properly calculated value.
>>> +
>>>    Message types
>>>    -------------
>>>
>>> diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
>>> 47f8b89..426b23e 100644
>>> --- a/hw/net/vhost_net.c
>>> +++ b/hw/net/vhost_net.c
>>> @@ -157,6 +157,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions
>>> *options)
>>>
>>>        net->dev.nvqs = 2;
>>>        net->dev.vqs = net->vqs;
>>> +    net->dev.vq_index = net->nc->queue_index;
>>>
>>>        r = vhost_dev_init(&net->dev, options->opaque,
>>>                           options->backend_type, options->force); @@
>>> -267,7 +268,7 @@ static void vhost_net_stop_one(struct vhost_net *net,
>>>            for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
>>>                const VhostOps *vhost_ops = net->dev.vhost_ops;
>>>                int r = vhost_ops->vhost_call(&net->dev, VHOST_RESET_OWNER,
>>> -                                          NULL);
>>> +                                          &file);
>>>                assert(r >= 0);
>>>            }
>>>        }
>>> diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index
>>> e7ab829..d6f2163 100644
>>> --- a/hw/virtio/vhost-user.c
>>> +++ b/hw/virtio/vhost-user.c
>>> @@ -210,7 +210,12 @@ static int vhost_user_call(struct vhost_dev
>>> *dev,
>> unsigned long int request,
>>>            break;
>>>
>>>        case VHOST_SET_OWNER:
>>> +        break;
>>> +
>>>        case VHOST_RESET_OWNER:
>>> +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
>>> +        msg.state.index += dev->vq_index;
>>> +        msg.size = sizeof(m.state);
>>>            break;
>>>
>>>        case VHOST_SET_MEM_TABLE:
>>> @@ -253,17 +258,20 @@ static int vhost_user_call(struct vhost_dev
>>> *dev,
>> unsigned long int request,
>>>        case VHOST_SET_VRING_NUM:
>>>        case VHOST_SET_VRING_BASE:
>>>            memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
>>> +        msg.state.index += dev->vq_index;
>>>            msg.size = sizeof(m.state);
>>>            break;
>>>
>>>        case VHOST_GET_VRING_BASE:
>>>            memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
>>> +        msg.state.index += dev->vq_index;
>>>            msg.size = sizeof(m.state);
>>>            need_reply = 1;
>>>            break;
>>>
>>>        case VHOST_SET_VRING_ADDR:
>>>            memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr));
>>> +        msg.addr.index += dev->vq_index;
>>>            msg.size = sizeof(m.addr);
>>>            break;
>>>
>>> @@ -271,7 +279,7 @@ static int vhost_user_call(struct vhost_dev
>>> *dev,
>> unsigned long int request,
>>>        case VHOST_SET_VRING_CALL:
>>>        case VHOST_SET_VRING_ERR:
>>>            file = arg;
>>> -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
>>> +        msg.u64 = (file->index + dev->vq_index) &
>>> + VHOST_USER_VRING_IDX_MASK;
>>>            msg.size = sizeof(m.u64);
>>>            if (ioeventfd_enabled() && file->fd > 0) {
>>>                fds[fd_num++] = file->fd; @@ -313,6 +321,7 @@ static
>>> int vhost_user_call(struct vhost_dev *dev, unsigned long int request,
>>>                    error_report("Received bad msg size.");
>>>                    return -1;
>>>                }
>>> +            msg.state.index -= dev->vq_index;
>>>                memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
>>>                break;
>>>            default:
>>> diff --git a/net/vhost-user.c b/net/vhost-user.c index
>>> 1d86a2b..904d8af 100644
>>> --- a/net/vhost-user.c
>>> +++ b/net/vhost-user.c
>>> @@ -121,35 +121,39 @@ static void net_vhost_user_event(void *opaque,
>> int event)
>>>        case CHR_EVENT_OPENED:
>>>            vhost_user_start(s);
>>>            net_vhost_link_down(s, false);
>>> -        error_report("chardev \"%s\" went up", s->chr->label);
>>> +        error_report("chardev \"%s\" went up", s->nc.info_str);
>>>            break;
>>>        case CHR_EVENT_CLOSED:
>>>            net_vhost_link_down(s, true);
>>>            vhost_user_stop(s);
>>> -        error_report("chardev \"%s\" went down", s->chr->label);
>>> +        error_report("chardev \"%s\" went down", s->nc.info_str);
>>>            break;
>>>        }
>>>    }
>>>
>>>    static int net_vhost_user_init(NetClientState *peer, const char *device,
>>> -                               const char *name, CharDriverState *chr)
>>> +                               const char *name, CharDriverState *chr,
>>> +                               uint32_t queues)
>>>    {
>>>        NetClientState *nc;
>>>        VhostUserState *s;
>>> +    int i;
>>>
>>> -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
>> name);
>>> +    for (i = 0; i < queues; i++) {
>>> +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
>>> + device, name);
>>>
>>> -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
>>> -             chr->label);
>>> +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
>>> +                 i, chr->label);
>>>
>>> -    s = DO_UPCAST(VhostUserState, nc, nc);
>>> +        s = DO_UPCAST(VhostUserState, nc, nc);
>>>
>>> -    /* We don't provide a receive callback */
>>> -    s->nc.receive_disabled = 1;
>>> -    s->chr = chr;
>>> -
>>> -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event,
>> s);
>>> +        /* We don't provide a receive callback */
>>> +        s->nc.receive_disabled = 1;
>>> +        s->chr = chr;
>>> +        s->nc.queue_index = i;
>>>
>>> +        qemu_chr_add_handlers(s->chr, NULL, NULL,
>>> + net_vhost_user_event,
>> s);
>>> +    }
>>>        return 0;
>>>    }
>>>
>>> @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts,
>> void *opaque)
>>>    int net_init_vhost_user(const NetClientOptions *opts, const char *name,
>>>                            NetClientState *peer)
>>>    {
>>> +    uint32_t queues;
>>>        const NetdevVhostUserOptions *vhost_user_opts;
>>>        CharDriverState *chr;
>>>
>>> @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions
>> *opts, const char *name,
>>>            return -1;
>>>        }
>>>
>>> +    /* number of queues for multiqueue */
>>> +    if (vhost_user_opts->has_queues) {
>>> +        queues = vhost_user_opts->queues;
>>> +    } else {
>>> +        queues = 1;
>>> +    }
>>>
>>> -    return net_vhost_user_init(peer, "vhost_user", name, chr);
>>> +    return net_vhost_user_init(peer, "vhost_user", name, chr,
>>> + queues);
>>>    }
>>> diff --git a/qapi-schema.json b/qapi-schema.json index
>>> f97ffa1..00791dd 100644
>>> --- a/qapi-schema.json
>>> +++ b/qapi-schema.json
>>> @@ -2444,12 +2444,16 @@
>>>    #
>>>    # @vhostforce: #optional vhost on for non-MSIX virtio guests (default:
>> false).
>>>    #
>>> +# @queues: #optional number of queues to be created for multiqueue
>> vhost-user
>>> +#          (default: 1) (Since 2.4)
>>> +#
>>>    # Since 2.1
>>>    ##
>>>    { 'struct': 'NetdevVhostUserOptions',
>>>      'data': {
>>>        'chardev':        'str',
>>> -    '*vhostforce':    'bool' } }
>>> +    '*vhostforce':    'bool',
>>> +    '*queues':        'uint32' } }
>>>
>>>    ##
>>>    # @NetClientOptions
>>> diff --git a/qemu-options.hx b/qemu-options.hx index
>>> ec356f6..dad035e
>>> 100644
>>> --- a/qemu-options.hx
>>> +++ b/qemu-options.hx
>>> @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to
>>> a
>> QEMU "vlan" instead of a single
>>>    netdev.  @code{-net} and @code{-device} with parameter
>>> @option{vlan}
>> create the
>>>    required hub automatically.
>>>
>>> -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
>>> +@item -netdev
>>> +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
>>>
>>>    Establish a vhost-user netdev, backed by a chardev @var{id}. The
>>> chardev
>> should
>>>    be a unix domain socket backed one. The vhost-user uses a
>>> specifically
>> defined
>>>    protocol to pass vhost ioctl replacement messages to an
>>> application on the
>> other
>>>    end of the socket. On non-MSIX guests, the feature can be forced
>>> with -@var{vhostforce}.
>>> +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of
>>> +queues to be created for multiqueue vhost-user.
>>>
>>>    Example:
>>>    @example
>>>
>

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-31  8:29               ` Ouyang, Changchun
@ 2015-08-31 11:30                 ` Michael S. Tsirkin
  2015-08-31 15:04                   ` Eric Blake
  2015-09-01  9:20                   ` Yuanhan Liu
  0 siblings, 2 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-08-31 11:30 UTC (permalink / raw)
  To: Ouyang, Changchun
  Cc: snabb-devel, Liu, Yuanhan, thibaut.collet, qemu-devel,
	n.nikolaev, luke, Long, Thomas

On Mon, Aug 31, 2015 at 08:29:39AM +0000, Ouyang, Changchun wrote:
> 
> 
> > -----Original Message-----
> > From: Michael S. Tsirkin [mailto:mst@redhat.com]
> > Sent: Sunday, August 30, 2015 2:16 PM
> > To: Ouyang, Changchun
> > Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > luke@snabb.co; Long, Thomas; Liu, Yuanhan
> > Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue
> > support
> > 
> > On Fri, Aug 28, 2015 at 01:53:39AM +0000, Ouyang, Changchun wrote:
> > > Hi Michael,
> > >
> > > Thanks for your response!
> > >
> > > > -----Original Message-----
> > > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > > Sent: Thursday, August 27, 2015 9:05 PM
> > > > To: Ouyang, Changchun
> > > > Cc: snabb-devel@googlegroups.com; qemu-devel@nongnu.org;
> > > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > > luke@snabb.co; Long, Thomas; Liu, Yuanhan
> > > > Subject: Re: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > > queue support
> > > >
> > > > On Tue, Aug 25, 2015 at 03:25:54AM +0000, Ouyang, Changchun wrote:
> > > > > Hi Michael,
> > > > >
> > > > > > -----Original Message-----
> > > > > > From: snabb-devel@googlegroups.com [mailto:snabb-
> > > > > > devel@googlegroups.com] On Behalf Of Michael S. Tsirkin
> > > > > > Sent: Thursday, August 13, 2015 5:19 PM
> > > > > > To: Ouyang, Changchun
> > > > > > Cc: qemu-devel@nongnu.org; snabb-devel@googlegroups.com;
> > > > > > thibaut.collet@6wind.com; n.nikolaev@virtualopensystems.com;
> > > > > > luke@snabb.co; Long, Thomas
> > > > > > Subject: [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi
> > > > > > queue support
> > > > > >
> > > > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > > > Based on patch by Nikolay Nikolaev:
> > > > > > > Vhost-user will implement the multi queue support in a similar
> > > > > > > way to what vhost already has - a separate thread for each queue.
> > > > > > > To enable the multi queue functionality - a new command line
> > > > > > > parameter "queues" is introduced for the vhost-user netdev.
> > > > > > >
> > > > > > > The RESET_OWNER change is based on commit:
> > > > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > > > If it is reverted, the patch need update for it accordingly.
> > > > > > >
> > > > > > > Signed-off-by: Nikolay Nikolaev
> > > > > > > <n.nikolaev@virtualopensystems.com>
> > > > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > > > > ---
> > > > > > > Changes since v5:
> > > > > > >  - fix the message descption for VHOST_RESET_OWNER in
> > > > > > > vhost-user txt
> > > > > > >
> > > > > > > Changes since v4:
> > > > > > >  - remove the unnecessary trailing '\n'
> > > > > > >
> > > > > > > Changes since v3:
> > > > > > >  - fix one typo and wrap one long line
> > > > > > >
> > > > > > > Changes since v2:
> > > > > > >  - fix vq index issue for set_vring_call
> > > > > > >    When it is the case of VHOST_SET_VRING_CALL, The vq_index
> > > > > > > is not
> > > > > > initialized before it is used,
> > > > > > >    thus it could be a random value. The random value leads to
> > > > > > > crash in vhost
> > > > > > after passing down
> > > > > > >    to vhost, as vhost use this random value to index an array index.
> > > > > > >  - fix the typo in the doc and description
> > > > > > >  - address vq index for reset_owner
> > > > > > >
> > > > > > > Changes since v1:
> > > > > > >  - use s->nc.info_str when bringing up/down the backend
> > > > > > >
> > > > > > >  docs/specs/vhost-user.txt |  7 ++++++-
> > > > > > >  hw/net/vhost_net.c        |  3 ++-
> > > > > > >  hw/virtio/vhost-user.c    | 11 ++++++++++-
> > > > > > >  net/vhost-user.c          | 37 ++++++++++++++++++++++++------------
> > -
> > > > > > >  qapi-schema.json          |  6 +++++-
> > > > > > >  qemu-options.hx           |  5 +++--
> > > > > > >  6 files changed, 50 insertions(+), 19 deletions(-)
> > > > > > >
> > > > > > > diff --git a/docs/specs/vhost-user.txt
> > > > > > > b/docs/specs/vhost-user.txt index 70da3b1..9390f89 100644
> > > > > > > --- a/docs/specs/vhost-user.txt
> > > > > > > +++ b/docs/specs/vhost-user.txt
> > > > > > > @@ -135,6 +135,11 @@ As older slaves don't support negotiating
> > > > > > > protocol features,  a feature bit was dedicated for this purpose:
> > > > > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > > > > >
> > > > > > > +Multi queue support
> > > > > > > +-------------------
> > > > > > > +The protocol supports multiple queues by setting all index
> > > > > > > +fields in the sent messages to a properly calculated value.
> > > > > > > +
> > > > > > >  Message types
> > > > > > >  -------------
> > > > > > >
> > > > > > > @@ -198,7 +203,7 @@ Message types
> > > > > > >
> > > > > > >        Id: 4
> > > > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > > > -      Master payload: N/A
> > > > > > > +      Master payload: vring state description
> > > > > > >
> > > > > > >        Issued when a new connection is about to be closed. The
> > > > > > > Master
> > > > will no
> > > > > > >        longer own this connection (and will usually close it).
> > > > > >
> > > > > > This is an interface change, isn't it?
> > > > > > We can't make it unconditionally, need to make it dependent on a
> > > > > > protocol flag.
> > > >
> > > >
> > > > Pls remember to fix this one.
> > > >
> > > > > >
> > > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > > > > 1f25cb3..9cd6c05 100644
> > > > > > > --- a/hw/net/vhost_net.c
> > > > > > > +++ b/hw/net/vhost_net.c
> > > > > > > @@ -159,6 +159,7 @@ struct vhost_net
> > > > > > > *vhost_net_init(VhostNetOptions
> > > > > > > *options)
> > > > > > >
> > > > > > >      net->dev.nvqs = 2;
> > > > > > >      net->dev.vqs = net->vqs;
> > > > > > > +    net->dev.vq_index = net->nc->queue_index;
> > > > > > >
> > > > > > >      r = vhost_dev_init(&net->dev, options->opaque,
> > > > > > >                         options->backend_type,
> > > > > > > options->force); @@
> > > > > > > -269,7 +270,7 @@ static void vhost_net_stop_one(struct
> > > > > > > vhost_net
> > > > *net,
> > > > > > >          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
> > > > > > >              const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > > > > >              int r = vhost_ops->vhost_call(&net->dev,
> > VHOST_RESET_OWNER,
> > > > > > > -                                          NULL);
> > > > > > > +                                          &file);
> > > > > > >              assert(r >= 0);
> > > > > > >          }
> > > > > > >      }
> > > > > > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> > > > > > > index 27ba035..fb11d4c 100644
> > > > > > > --- a/hw/virtio/vhost-user.c
> > > > > > > +++ b/hw/virtio/vhost-user.c
> > > > > > > @@ -219,7 +219,12 @@ static int vhost_user_call(struct
> > > > > > > vhost_dev *dev,
> > > > > > unsigned long int request,
> > > > > > >          break;
> > > > > > >
> > > > > > >      case VHOST_USER_SET_OWNER:
> > > > > > > +        break;
> > > > > > > +
> > > > > > >      case VHOST_USER_RESET_OWNER:
> > > > > > > +        memcpy(&msg.state, arg, sizeof(struct vhost_vring_state));
> > > > > > > +        msg.state.index += dev->vq_index;
> > > > > > > +        msg.size = sizeof(m.state);
> > > > > > >          break;
> > > > > > >
> > > > > > >      case VHOST_USER_SET_MEM_TABLE:
> > > > > > > @@ -262,17 +267,20 @@ static int vhost_user_call(struct
> > > > > > > vhost_dev *dev,
> > > > > > unsigned long int request,
> > > > > > >      case VHOST_USER_SET_VRING_NUM:
> > > > > > >      case VHOST_USER_SET_VRING_BASE:
> > > > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > > > vhost_vring_state));
> > > > > > > +        msg.state.index += dev->vq_index;
> > > > > > >          msg.size = sizeof(m.state);
> > > > > > >          break;
> > > > > > >
> > > > > > >      case VHOST_USER_GET_VRING_BASE:
> > > > > > >          memcpy(&msg.state, arg, sizeof(struct
> > > > > > > vhost_vring_state));
> > > > > > > +        msg.state.index += dev->vq_index;
> > > > > > >          msg.size = sizeof(m.state);
> > > > > > >          need_reply = 1;
> > > > > > >          break;
> > > > > > >
> > > > > > >      case VHOST_USER_SET_VRING_ADDR:
> > > > > > >          memcpy(&msg.addr, arg, sizeof(struct
> > > > > > > vhost_vring_addr));
> > > > > > > +        msg.addr.index += dev->vq_index;
> > > > > > >          msg.size = sizeof(m.addr);
> > > > > > >          break;
> > > > > > >
> > > > > > > @@ -280,7 +288,7 @@ static int vhost_user_call(struct
> > > > > > > vhost_dev *dev,
> > > > > > unsigned long int request,
> > > > > > >      case VHOST_USER_SET_VRING_CALL:
> > > > > > >      case VHOST_USER_SET_VRING_ERR:
> > > > > > >          file = arg;
> > > > > > > -        msg.u64 = file->index & VHOST_USER_VRING_IDX_MASK;
> > > > > > > +        msg.u64 = (file->index + dev->vq_index) &
> > > > > > > + VHOST_USER_VRING_IDX_MASK;
> > > > > > >          msg.size = sizeof(m.u64);
> > > > > > >          if (ioeventfd_enabled() && file->fd > 0) {
> > > > > > >              fds[fd_num++] = file->fd; @@ -322,6 +330,7 @@
> > > > > > > static int vhost_user_call(struct vhost_dev *dev, unsigned long int
> > request,
> > > > > > >                  error_report("Received bad msg size.");
> > > > > > >                  return -1;
> > > > > > >              }
> > > > > > > +            msg.state.index -= dev->vq_index;
> > > > > > >              memcpy(arg, &msg.state, sizeof(struct vhost_vring_state));
> > > > > > >              break;
> > > > > > >          default:
> > > > > > > diff --git a/net/vhost-user.c b/net/vhost-user.c index
> > > > > > > 1d86a2b..904d8af 100644
> > > > > > > --- a/net/vhost-user.c
> > > > > > > +++ b/net/vhost-user.c
> > > > > > > @@ -121,35 +121,39 @@ static void net_vhost_user_event(void
> > > > > > > *opaque,
> > > > > > int event)
> > > > > > >      case CHR_EVENT_OPENED:
> > > > > > >          vhost_user_start(s);
> > > > > > >          net_vhost_link_down(s, false);
> > > > > > > -        error_report("chardev \"%s\" went up", s->chr->label);
> > > > > > > +        error_report("chardev \"%s\" went up",
> > > > > > > + s->nc.info_str);
> > > > > > >          break;
> > > > > > >      case CHR_EVENT_CLOSED:
> > > > > > >          net_vhost_link_down(s, true);
> > > > > > >          vhost_user_stop(s);
> > > > > > > -        error_report("chardev \"%s\" went down", s->chr->label);
> > > > > > > +        error_report("chardev \"%s\" went down",
> > > > > > > + s->nc.info_str);
> > > > > > >          break;
> > > > > > >      }
> > > > > > >  }
> > > >
> > > > BTW this seems pretty hacky: you get multiple messages when one
> > > > client connects. Why add multiple event listeners to the same chat device?
> > > >
> > > >
> > > > > > >
> > > > > > >  static int net_vhost_user_init(NetClientState *peer, const char
> > *device,
> > > > > > > -                               const char *name, CharDriverState *chr)
> > > > > > > +                               const char *name, CharDriverState *chr,
> > > > > > > +                               uint32_t queues)
> > > > > > >  {
> > > > > > >      NetClientState *nc;
> > > > > > >      VhostUserState *s;
> > > > > > > +    int i;
> > > > > > >
> > > > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > > > > > name);
> > > > > > > +    for (i = 0; i < queues; i++) {
> > > > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > > > > + device, name);
> > > > > > >
> > > > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > > > -             chr->label);
> > > > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d
> > to %s",
> > > > > > > +                 i, chr->label);
> > > > > > >
> > > > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > >
> > > > > > > -    /* We don't provide a receive callback */
> > > > > > > -    s->nc.receive_disabled = 1;
> > > > > > > -    s->chr = chr;
> > > > > > > -
> > > > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > > net_vhost_user_event,
> > > > > > s);
> > > > > > > +        /* We don't provide a receive callback */
> > > > > > > +        s->nc.receive_disabled = 1;
> > > > > > > +        s->chr = chr;
> > > > > > > +        s->nc.queue_index = i;
> > > > > > >
> > > > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> > > > > > > + net_vhost_user_event,
> > > > > > s);
> > > > > > > +    }
> > > > > > >      return 0;
> > > > > > >  }
> > > > > > >
> > > > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> > > > *opts,
> > > > > > > void *opaque)
> > > > > >
> > > > > >
> > > > > > There are two problems here:
> > > > > >
> > > > > > 1. we don't really know that the backend
> > > > > >    is able to support the requested number of queues.
> > > > > >    If not, everything will fail, silently.
> > > > > >    A new message to query the # of queues could help, though
> > > > > >    I'm not sure what can be done on failure. Fail connection?
> > > > > >
> > > > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > > > >    on the same socket.
> > > > > >
> > > > > I think it is tough to resolve these 2 comments, as the current
> > > > > message is either vhost-dev based or virt-queue based, The
> > > > > multiple
> > > > queues(pair) feature use multiple vhost-devs to implement itself.
> > > > > For #1
> > > > > So the queue number is something should be seen in the upper level
> > > > > of
> > > > vhost-dev rather than inside the vhost-dev.
> > > > > For each vhost-net, there are 2 virt-queues, one is for Rx the other is
> > for Tx.
> > > > > introduce the virt-queue pair number into the vhost-dev? But I
> > > > > don't think it is good, as for each vhost-dev, there is only one virt-
> > queue pair.
> > > > >
> > > > > Where should I put the virt-queue pair number to? I don't get the
> > > > > perfect
> > > > answer till now. Any suggestion is welcome.
> > > > >
> > > > > Could we assume the vhost backend has the ability to create enough
> > > > > virt-queue pair(e.g. 0x8000 is the max) if qemu require Vhost
> > > > > backend to do it. If it is correct, we don't need get virt-queue
> > > > > pair number from
> > > > vhost backend, as vhost backend can Create all virt-queue pair
> > > > required by qemu.
> > > > > The virtio frontend(on guest) has the flexibility to enable which
> > > > > virt-queue
> > > > according to its own capability, qemu can do it by using
> > > > > Set_vring_flag message to notify vhost backend.
> > > >
> > > > I'm reluctant to agree to this. Implementations tend to get this wrong, e.g.
> > > > they would only test with 2 queues and assume everything is OK.
> > > > With an explicit message, this seems more robust.
> > > >
> > > > Why is it so hard to implement?  User specifies queues=X.
> > > > Can't we simply validate that backend supports this # of queues?
> > >
> > > Yes exactly in the qemu, we use qeueus=X to specify the virt-queue pair
> > number.
> > > In my previous comments, I am talking about how to resolve such scenario:
> > > vhost backend specify the queues=Y(Y != X, e.g. X = 8, Y = 4), how
> > > vhost backend tell qemu that it only has the capability of max
> > > virt-queue pair is 4, and qemu need update its max queue number
> > according to its own parameter and the max value from vhost back end.
> > >
> > > Do you think whether this scenario makes sense or not?
> > 
> > No, I think that if we can't support the number requested by user, QEMU can
> > simply exit.
> 
> Well, both values are input from user, for some unknown reason, they are different.
> When startup the vhost backend, user specify 4 queues, like:
> Vhost-user ...  -queues 4      # Y=4
> When startup the guest, user specify 8 queues, like:
> Qemu-kvm ... -queues 8      # X=8
> 
> Vhost backend can't support the queues number as much as the guest/qemu requires,
> I think you mean we should let qemu exit in such a case, right?   

Exactly.

> Then how about the other case:
> When startup the vhost backend, user specify 8 queues, like:
> Vhost-user ...  -queues 8      # Y=8
> When startup the guest, user specify 4 queues, like:
> Qemu-kvm ... -queues 4      # X=4
> 
> Vhost backend CAN support the queues number as much as the guest/qemu requires,
> And qemu don't want enable all of them(8 in the case), just part of them(only 4 from 8).
> Will qemu exit or go forward(of course with 4 queues)? 

I think it must go forward since guest does not have to
configure all queues anyway - and that's built in to virtio spec.

Note that # of queues in actual use in fact changes dynamically
too, without restaring the device.

> > 
> > > If yes, then we should consider extend new message to allow vhost
> > > backend communicate Its virt-queue number to qemu.
> > 
> > Yes, conditional on the mq protocol flag.
> > 
> > > More than that, either we need change codes to allow each net_client
> > > has more than
> > > 1 virt-queue pair(==2 virt-queue, one for Rx, the other for Tx), Or
> > > another better solution for that?
> > 
> > I'm not sure why is that required for the above.
> > 
> > > >
> > > >
> > > > > For #2
> > > > > The memory table message is also vhost-dev based, it wouldn't hurt
> > > > > we send it a few times, vhost backend could Keep it vhost-dev
> > > > > based too, or keep it once(keep it when first time and ignore in
> > > > > rest messages from the same connected-fd) Any other good
> > > > > suggestion is welcome too
> > > > > :-)
> > > >
> > > > Add code in vhost-user to skip sending the useless messages?  Yes
> > > > they seem harmless but implementations tend to develop dependencies
> > > > on such bugs, then we get to maintain them forever.
> > >
> > > Considering we use multiple vhost_net(multiple net_client) to fulfill
> > multiple virt-queue pairs.
> > > So only the first virt-queue pair will send the set-memory-table, others
> > won't do it.
> > > Is that ok? so apparently each net client will have difference in message
> > count.
> > > The first net client will have the message of set memory table, others have
> > not.
> > >
> > > Thanks
> > > Changchun
> > 
> > But all these clients use the same unix domain socket, correct?
> Yes, correct
> 
> > If so, I don't think it matters that internally in qemu they use different net
> > clients. From the external point of view, it looks like a single message is sent
> > on a single socket.
> > 
> > > >
> > > > > >
> > > > > >
> > > > > > >  int net_init_vhost_user(const NetClientOptions *opts, const
> > > > > > > char
> > > > *name,
> > > > > > >                          NetClientState *peer)  {
> > > > > > > +    uint32_t queues;
> > > > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > > > >      CharDriverState *chr;
> > > > > > >
> > > > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> > > > > > > NetClientOptions
> > > > > > *opts, const char *name,
> > > > > > >          return -1;
> > > > > > >      }
> > > > > > >
> > > > > > > +    /* number of queues for multiqueue */
> > > > > > > +    if (vhost_user_opts->has_queues) {
> > > > > > > +        queues = vhost_user_opts->queues;
> > > > > > > +    } else {
> > > > > > > +        queues = 1;
> > > > > > > +    }
> > > > > > >
> > > > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > > > > + queues);
> > > > > > >  }
> > > > > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > > > > f97ffa1..51e40ce 100644
> > > > > > > --- a/qapi-schema.json
> > > > > > > +++ b/qapi-schema.json
> > > > > > > @@ -2444,12 +2444,16 @@
> > > > > > >  #
> > > > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests
> > (default:
> > > > > > false).
> > > > > > >  #
> > > > > > > +# @queues: #optional number of queues to be created for
> > > > > > > +multiqueue
> > > > > > vhost-user
> > > > > > > +#          (default: 1) (Since 2.5)
> > > > > > > +#
> > > > > > >  # Since 2.1
> > > > > > >  ##
> > > > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > > > >    'data': {
> > > > > > >      'chardev':        'str',
> > > > > > > -    '*vhostforce':    'bool' } }
> > > > > > > +    '*vhostforce':    'bool',
> > > > > > > +    '*queues':        'uint32' } }
> > > > > > >
> > > > > > >  ##
> > > > > > >  # @NetClientOptions
> > > > > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > > > > ec356f6..dad035e
> > > > > > > 100644
> > > > > > > --- a/qemu-options.hx
> > > > > > > +++ b/qemu-options.hx
> > > > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a
> > > > > > > NIC to a QEMU "vlan" instead of a single  netdev.  @code{-net}
> > > > > > > and @code{-device} with parameter @option{vlan} create the
> > > > > > > required hub
> > > > > > automatically.
> > > > > > >
> > > > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > > > +@item -netdev
> > > > > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > > > >
> > > > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}.
> > > > > > > The chardev should  be a unix domain socket backed one. The
> > > > > > > vhost-user uses a specifically defined  protocol to pass vhost
> > > > > > > ioctl replacement messages to an application on the other  end
> > > > > > > of the socket. On non-MSIX guests, the feature can be forced
> > > > > > > with -
> > > > @var{vhostforce}.
> > > > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number
> > > > > > > +of queues to be created for multiqueue vhost-user.
> > > > > > >
> > > > > > >  Example:
> > > > > > >  @example
> > > > > > > --
> > > > > > > 1.8.4.2
> > > > > > >
> > > > > >
> > > > > > --
> > > > > > You received this message because you are subscribed to the
> > > > > > Google Groups "Snabb Switch development" group.
> > > > > > To unsubscribe from this group and stop receiving emails from
> > > > > > it, send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > > > > To post to this group, send an email to snabb-
> > devel@googlegroups.com.
> > > > > > Visit this group at http://groups.google.com/group/snabb-devel.
> > > >
> > > > --
> > > > You received this message because you are subscribed to the Google
> > > > Groups "Snabb Switch development" group.
> > > > To unsubscribe from this group and stop receiving emails from it,
> > > > send an email to snabb-devel+unsubscribe@googlegroups.com.
> > > > To post to this group, send an email to snabb-devel@googlegroups.com.
> > > > Visit this group at http://groups.google.com/group/snabb-devel.

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-31 11:30                 ` Michael S. Tsirkin
@ 2015-08-31 15:04                   ` Eric Blake
  2015-09-01  9:20                   ` Yuanhan Liu
  1 sibling, 0 replies; 44+ messages in thread
From: Eric Blake @ 2015-08-31 15:04 UTC (permalink / raw)
  To: Michael S. Tsirkin, Ouyang, Changchun
  Cc: snabb-devel, Liu, Yuanhan, thibaut.collet, qemu-devel,
	n.nikolaev, luke, Long, Thomas

[-- Attachment #1: Type: text/plain, Size: 1336 bytes --]

On 08/31/2015 05:30 AM, Michael S. Tsirkin wrote:
> On Mon, Aug 31, 2015 at 08:29:39AM +0000, Ouyang, Changchun wrote:

>>>>>>> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
>>>>>>>> Based on patch by Nikolay Nikolaev:

When you start to have this much nested quoting,...

>>>>>>>> -269,7 +270,7 @@ static void vhost_net_stop_one(struct
>>>>>>>> vhost_net
>>>>> *net,
>>>>>>>>          for (file.index = 0; file.index < net->dev.nvqs; ++file.index) {
>>>>>>>>              const VhostOps *vhost_ops = net->dev.vhost_ops;
>>>>>>>>              int r = vhost_ops->vhost_call(&net->dev,
>>> VHOST_RESET_OWNER,

...line wrapping of the quotes gets funky and starts mis-attributing
portions of lines to the wrong quote level.

>> Vhost backend can't support the queues number as much as the guest/qemu requires,
>> I think you mean we should let qemu exit in such a case, right?   
> 
> Exactly.

And mis-attribution makes it that much harder to find the real content
being added further down in the middle of 28k of mostly-quoted message.

Please remember that it is okay to trim messages to the relevant
portions, to make it easier for readers to quickly get at the new content.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-13  9:18     ` Michael S. Tsirkin
  2015-08-13 10:24       ` Maxime Leroy
  2015-08-25  3:25       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
@ 2015-09-01  9:13       ` Yuanhan Liu
  2015-09-01 10:07         ` Michael S. Tsirkin
  2015-09-07 11:07       ` Marcel Apfelbaum
  3 siblings, 1 reply; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01  9:13 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > Based on patch by Nikolay Nikolaev:
> > Vhost-user will implement the multi queue support in a similar way
> > to what vhost already has - a separate thread for each queue.
> > To enable the multi queue functionality - a new command line parameter
> > "queues" is introduced for the vhost-user netdev.
> > 
> > The RESET_OWNER change is based on commit:
> >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > If it is reverted, the patch need update for it accordingly.
> > 
> > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
[snip...]
> > @@ -198,7 +203,7 @@ Message types
> >  
> >        Id: 4
> >        Equivalent ioctl: VHOST_RESET_OWNER
> > -      Master payload: N/A
> > +      Master payload: vring state description
> >  
> >        Issued when a new connection is about to be closed. The Master will no
> >        longer own this connection (and will usually close it).
> 
> This is an interface change, isn't it?
> We can't make it unconditionally, need to make it dependent
> on a protocol flag.

Hi Michael,

I'm wondering why we need a payload here, as we don't do that for
VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
connect is about to be close doesn't make sense to me. Instead,
we should clean up all queue pair when VHOST_RESET_OWNER message
is received, right?

> 
> 
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > index 1f25cb3..9cd6c05 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
[snip...]
> >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > -                               const char *name, CharDriverState *chr)
> > +                               const char *name, CharDriverState *chr,
> > +                               uint32_t queues)
> >  {
> >      NetClientState *nc;
> >      VhostUserState *s;
> > +    int i;
> >  
> > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > +    for (i = 0; i < queues; i++) {
> > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> >  
> > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > -             chr->label);
> > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > +                 i, chr->label);
> >  
> > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > +        s = DO_UPCAST(VhostUserState, nc, nc);
> >  
> > -    /* We don't provide a receive callback */
> > -    s->nc.receive_disabled = 1;
> > -    s->chr = chr;
> > -
> > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > +        /* We don't provide a receive callback */
> > +        s->nc.receive_disabled = 1;
> > +        s->chr = chr;
> > +        s->nc.queue_index = i;
> >  
> > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > +    }
> >      return 0;
> >  }
> >  
> > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
> 
> 
> There are two problems here:
> 
> 1. we don't really know that the backend
>    is able to support the requested number of queues.
>    If not, everything will fail, silently.
>    A new message to query the # of queues could help, though
>    I'm not sure what can be done on failure. Fail connection?

What I'm thinking is we may do:

- introduce a feature flag, for indicating we support MQ or not.

  We query this flag only when # of queues given is > 1. We exit
  if it not matches.

- invoke vhost_dev init repeatedly for # of queues given, unless
  something wrong happened, which basically means the backend
  can not support such # of queues; we then quit.

  We could, as you suggested, add an another message to query
  the max # queues the backend support. However, judging we have
  to check the return value of setting up a single queue pair,
  which already gives feedback when the backed is not able to
  support requested # of queues, we could save such message,
  though it's easy to implement :)

> 
> 2. each message (e.g. set memory table) is sent multiple times,
>    on the same socket.

Yeah, for there is a single socket opening there, it's not necessary
to send messages like SET_MEM_TABLE multiple times. But for other
messages that relate to to a specific vring, we have to send N times,
don't we?

So, I'm wondering could we categorize the message in two types: vring
specific and none-vring specific. For vring specific, we send it N
times, with the vhost_dev->vq_index telling which one queue pair
we have interest.

For none-vring specific, we just send it once for first queue pair
(vhost_dev->queue == 0), just like what we did for tap: we launch
qemu-ifup/down script only for the first queue pair.

Comments? (And sorry if I made some silly comments, as I'm pretty
new to this community, say just have read about 2 weeks code).

	--yliu

> 
> 
> 
> >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> >                          NetClientState *peer)
> >  {
> > +    uint32_t queues;
> >      const NetdevVhostUserOptions *vhost_user_opts;
> >      CharDriverState *chr;
> >  
> > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> >          return -1;
> >      }
> >  
> > +    /* number of queues for multiqueue */
> > +    if (vhost_user_opts->has_queues) {
> > +        queues = vhost_user_opts->queues;
> > +    } else {
> > +        queues = 1;
> > +    }
> >  
> > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
> >  }
> > diff --git a/qapi-schema.json b/qapi-schema.json
> > index f97ffa1..51e40ce 100644
> > --- a/qapi-schema.json
> > +++ b/qapi-schema.json
> > @@ -2444,12 +2444,16 @@
> >  #
> >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
> >  #
> > +# @queues: #optional number of queues to be created for multiqueue vhost-user
> > +#          (default: 1) (Since 2.5)
> > +#
> >  # Since 2.1
> >  ##
> >  { 'struct': 'NetdevVhostUserOptions',
> >    'data': {
> >      'chardev':        'str',
> > -    '*vhostforce':    'bool' } }
> > +    '*vhostforce':    'bool',
> > +    '*queues':        'uint32' } }
> >  
> >  ##
> >  # @NetClientOptions
> > diff --git a/qemu-options.hx b/qemu-options.hx
> > index ec356f6..dad035e 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
> >  netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
> >  required hub automatically.
> >  
> > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> >  
> >  Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
> >  be a unix domain socket backed one. The vhost-user uses a specifically defined
> >  protocol to pass vhost ioctl replacement messages to an application on the other
> >  end of the socket. On non-MSIX guests, the feature can be forced with
> > -@var{vhostforce}.
> > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> > +be created for multiqueue vhost-user.
> >  
> >  Example:
> >  @example
> > -- 
> > 1.8.4.2
> > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-08-13  9:22     ` Michael S. Tsirkin
  2015-08-24  1:50       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
@ 2015-09-01  9:16       ` Yuanhan Liu
  2015-09-01 10:09         ` Michael S. Tsirkin
  1 sibling, 1 reply; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01  9:16 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Thu, Aug 13, 2015 at 12:22:50PM +0300, Michael S. Tsirkin wrote:
> On Wed, Aug 12, 2015 at 02:25:42PM +0800, Ouyang Changchun wrote:
> > This patch is based on top of "vhost-user: protocol updates" series
> > proposed earlier by Michael S. Tsirkin.
> > 
> > Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
> > actual virt queue, which is similar to attach/detach queue for tap device.
> > virtio driver on guest doesn't have to use max virt queue pair, it could
> > enable any number of virt queue ranging from 1 to max virt queue pair.
> > 
> > It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.
> > 
> > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > ---
> > This is added since v5
> > 
> >  docs/specs/vhost-user.txt         | 17 +++++++++++++++++
> >  hw/net/vhost_net.c                | 18 ++++++++++++++++++
> >  hw/net/virtio-net.c               |  2 ++
> >  hw/virtio/vhost-user.c            | 35 +++++++++++++++++++++++++++++++++--
> >  include/hw/virtio/vhost-backend.h |  2 ++
> >  include/net/vhost_net.h           |  1 +
> >  6 files changed, 73 insertions(+), 2 deletions(-)
> > 
> > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > index 9390f89..cca3e5b 100644
> > --- a/docs/specs/vhost-user.txt
> > +++ b/docs/specs/vhost-user.txt
> > @@ -135,6 +135,10 @@ As older slaves don't support negotiating protocol features,
> >  a feature bit was dedicated for this purpose:
> >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> >  
> > +The Slave uses vring flag to notify the vhost-user whether one virtq is enabled
> > +or not. This request doesn't require replies:
> > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > +
> >  Multi queue support
> >  -------------------
> >  The protocol supports multiple queues by setting all index fields in the sent
> > @@ -306,3 +310,16 @@ Message types
> >        Bits (0-7) of the payload contain the vring index. Bit 8 is the
> >        invalid FD flag. This flag is set when there is no file descriptor
> >        in the ancillary data.
> > +
> > + * VHOST_USER_SET_VRING_FLAG
> > +
> > +      Id: 18
> > +      Equivalent ioctl: N/A
> > +      Master payload: vring state description
> > +
> > +      Set the flag(enable or disable) in the vring, the vhost user backend
> > +      enable or disable the vring according to state.num. Olny legal if feature
> > +      bit VHOST_USER_F_PROTOCOL_FEATURES is present in VHOST_USER_GET_FEATURE
> > +      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
> > +      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when state.num is
> > +      1, otherwise, the vring is disabled.
> > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > index 9cd6c05..5fa341c 100644
> > --- a/hw/net/vhost_net.c
> > +++ b/hw/net/vhost_net.c
> > @@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> >  
> >      return vhost_net;
> >  }
> > +
> > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > +{
> > +    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> > +        struct vhost_net *net = get_vhost_net(nc);
> > +        const VhostOps *vhost_ops = net->dev.vhost_ops;
> > +        if (vhost_ops->vhost_backend_mq_set_vring_flag)
> > +            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev, enable);
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  #else
> >  struct vhost_net *vhost_net_init(VhostNetOptions *options)
> >  {
> > @@ -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> >  {
> >      return 0;
> >  }
> > +
> > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > +{
> > +    return 0;
> > +}
> >  #endif
> > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> > index 3af6faf..272b77d 100644
> > --- a/hw/net/virtio-net.c
> > +++ b/hw/net/virtio-net.c
> > @@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
> >      }
> >  
> >      if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> > +        vhost_set_vring_flag(nc->peer, 1);
> >          return 0;
> >      }
> >  
> > @@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
> >      }
> >  
> >      if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
> > +        vhost_set_vring_flag(nc->peer, 0);
> >          return 0;
> >      }
> >  
> > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> > index fb11d4c..d806ce2 100644
> > --- a/hw/virtio/vhost-user.c
> > +++ b/hw/virtio/vhost-user.c
> > @@ -25,7 +25,8 @@
> >  
> >  #define VHOST_MEMORY_MAX_NREGIONS    8
> >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
> >  
> >  typedef enum VhostUserRequest {
> >      VHOST_USER_NONE = 0,
> > @@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
> >      VHOST_USER_SET_VRING_ERR = 14,
> >      VHOST_USER_GET_PROTOCOL_FEATURES = 15,
> >      VHOST_USER_SET_PROTOCOL_FEATURES = 16,
> > +    VHOST_USER_SET_VRING_FLAG = 18,
> >      VHOST_USER_MAX
> >  } VhostUserRequest;
> >  
> > @@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
> >      return 0;
> >  }
> >  
> > +static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned int enable)
> > +{
> > +    VhostUserMsg msg = { 0 };
> > +    int err;
> > +
> > +    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> > +
> > +    if ((dev->backend_features & ( 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
> > +        return -1;
> > +
> > +    if ((dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
> > +        return -1;
> > +
> > +    msg.request = VHOST_USER_SET_VRING_FLAG;
> > +    msg.flags = VHOST_USER_VERSION;
> > +    /* Set the virt queue pair index */
> > +    msg.state.index = dev->vq_index / 2;
> 
> Thinking about this, this means that the index value is specific to virtio net.
> This seems wrong.

How about adding a new field queue_index to vhost_dev structure? So that
we could get rid of it.

	--yliu
> 
> > +    msg.state.num = enable;
> > +    msg.size = sizeof msg.state;
> > +
> > +    err = vhost_user_write(dev, &msg, NULL, 0);
> > +    if (err < 0) {
> > +        return err;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> >  static int vhost_user_cleanup(struct vhost_dev *dev)
> >  {
> >      assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> > @@ -412,5 +442,6 @@ const VhostOps user_ops = {
> >          .backend_type = VHOST_BACKEND_TYPE_USER,
> >          .vhost_call = vhost_user_call,
> >          .vhost_backend_init = vhost_user_init,
> > -        .vhost_backend_cleanup = vhost_user_cleanup
> > +        .vhost_backend_cleanup = vhost_user_cleanup,
> > +        .vhost_backend_mq_set_vring_flag = vhost_user_set_vring_flag,
> >          };
> > diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
> > index e472f29..c394147 100644
> > --- a/include/hw/virtio/vhost-backend.h
> > +++ b/include/hw/virtio/vhost-backend.h
> > @@ -24,12 +24,14 @@ typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
> >               void *arg);
> >  typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
> >  typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
> > +typedef int (*vhost_backend_mq_set_vring_flag)(struct vhost_dev *dev, unsigned int enable);
> >  
> >  typedef struct VhostOps {
> >      VhostBackendType backend_type;
> >      vhost_call vhost_call;
> >      vhost_backend_init vhost_backend_init;
> >      vhost_backend_cleanup vhost_backend_cleanup;
> > +    vhost_backend_mq_set_vring_flag vhost_backend_mq_set_vring_flag;
> >  } VhostOps;
> >  
> >  extern const VhostOps user_ops;
> > diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> > index b1c18a3..9b76548 100644
> > --- a/include/net/vhost_net.h
> > +++ b/include/net/vhost_net.h
> > @@ -29,4 +29,5 @@ bool vhost_net_virtqueue_pending(VHostNetState *net, int n);
> >  void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
> >                                int idx, bool mask);
> >  VHostNetState *get_vhost_net(NetClientState *nc);
> > +int vhost_set_vring_flag(NetClientState * nc, unsigned int enable);
> >  #endif
> > -- 
> > 1.8.4.2
> > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-31 11:30                 ` Michael S. Tsirkin
  2015-08-31 15:04                   ` Eric Blake
@ 2015-09-01  9:20                   ` Yuanhan Liu
  2015-09-01  9:41                     ` Michael S. Tsirkin
  1 sibling, 1 reply; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01  9:20 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

On Mon, Aug 31, 2015 at 02:30:06PM +0300, Michael S. Tsirkin wrote:
[snip..] 
> > Then how about the other case:
> > When startup the vhost backend, user specify 8 queues, like:
> > Vhost-user ...  -queues 8      # Y=8
> > When startup the guest, user specify 4 queues, like:
> > Qemu-kvm ... -queues 4      # X=4
> > 
> > Vhost backend CAN support the queues number as much as the guest/qemu requires,
> > And qemu don't want enable all of them(8 in the case), just part of them(only 4 from 8).
> > Will qemu exit or go forward(of course with 4 queues)? 
> 
> I think it must go forward since guest does not have to
> configure all queues anyway - and that's built in to virtio spec.
> 
> Note that # of queues in actual use in fact changes dynamically
> too, without restaring the device.

May I know how do you do that? I mean, is there a public interface, like
by some commands? Or, by sending vhost messages?

	--yliu

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01  9:20                   ` Yuanhan Liu
@ 2015-09-01  9:41                     ` Michael S. Tsirkin
  2015-09-01 12:16                       ` Yuanhan Liu
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-01  9:41 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

On Tue, Sep 01, 2015 at 05:20:06PM +0800, Yuanhan Liu wrote:
> On Mon, Aug 31, 2015 at 02:30:06PM +0300, Michael S. Tsirkin wrote:
> [snip..] 
> > > Then how about the other case:
> > > When startup the vhost backend, user specify 8 queues, like:
> > > Vhost-user ...  -queues 8      # Y=8
> > > When startup the guest, user specify 4 queues, like:
> > > Qemu-kvm ... -queues 4      # X=4
> > > 
> > > Vhost backend CAN support the queues number as much as the guest/qemu requires,
> > > And qemu don't want enable all of them(8 in the case), just part of them(only 4 from 8).
> > > Will qemu exit or go forward(of course with 4 queues)? 
> > 
> > I think it must go forward since guest does not have to
> > configure all queues anyway - and that's built in to virtio spec.
> > 
> > Note that # of queues in actual use in fact changes dynamically
> > too, without restaring the device.
> 
> May I know how do you do that? I mean, is there a public interface, like
> by some commands? Or, by sending vhost messages?
> 
> 	--yliu

Using ethtool within guest. In fact, guests boot with a single queue,
you need to use ethtool to enable mq, specifying the # of queues.

-- 
MST

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01  9:13       ` [Qemu-devel] " Yuanhan Liu
@ 2015-09-01 10:07         ` Michael S. Tsirkin
  2015-09-01 12:15           ` Yuanhan Liu
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-01 10:07 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Tue, Sep 01, 2015 at 05:13:50PM +0800, Yuanhan Liu wrote:
> On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > Based on patch by Nikolay Nikolaev:
> > > Vhost-user will implement the multi queue support in a similar way
> > > to what vhost already has - a separate thread for each queue.
> > > To enable the multi queue functionality - a new command line parameter
> > > "queues" is introduced for the vhost-user netdev.
> > > 
> > > The RESET_OWNER change is based on commit:
> > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > If it is reverted, the patch need update for it accordingly.
> > > 
> > > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> [snip...]
> > > @@ -198,7 +203,7 @@ Message types
> > >  
> > >        Id: 4
> > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > -      Master payload: N/A
> > > +      Master payload: vring state description
> > >  
> > >        Issued when a new connection is about to be closed. The Master will no
> > >        longer own this connection (and will usually close it).
> > 
> > This is an interface change, isn't it?
> > We can't make it unconditionally, need to make it dependent
> > on a protocol flag.
> 
> Hi Michael,
> 
> I'm wondering why we need a payload here, as we don't do that for
> VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
> connect is about to be close doesn't make sense to me. Instead,
> we should clean up all queue pair when VHOST_RESET_OWNER message
> is received, right?

We really should rename VHOST_RESET_OWNER to VHOST_RESET_DEVICE.

And I agree, I don't think it needs a payload.


> > 
> > 
> > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > index 1f25cb3..9cd6c05 100644
> > > --- a/hw/net/vhost_net.c
> > > +++ b/hw/net/vhost_net.c
> [snip...]
> > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > -                               const char *name, CharDriverState *chr)
> > > +                               const char *name, CharDriverState *chr,
> > > +                               uint32_t queues)
> > >  {
> > >      NetClientState *nc;
> > >      VhostUserState *s;
> > > +    int i;
> > >  
> > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > > +    for (i = 0; i < queues; i++) {
> > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > >  
> > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > -             chr->label);
> > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > +                 i, chr->label);
> > >  
> > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > >  
> > > -    /* We don't provide a receive callback */
> > > -    s->nc.receive_disabled = 1;
> > > -    s->chr = chr;
> > > -
> > > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > +        /* We don't provide a receive callback */
> > > +        s->nc.receive_disabled = 1;
> > > +        s->chr = chr;
> > > +        s->nc.queue_index = i;
> > >  
> > > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > +    }
> > >      return 0;
> > >  }
> > >  
> > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
> > 
> > 
> > There are two problems here:
> > 
> > 1. we don't really know that the backend
> >    is able to support the requested number of queues.
> >    If not, everything will fail, silently.
> >    A new message to query the # of queues could help, though
> >    I'm not sure what can be done on failure. Fail connection?
> 
> What I'm thinking is we may do:
> 
> - introduce a feature flag, for indicating we support MQ or not.
> 
>   We query this flag only when # of queues given is > 1. We exit
>   if it not matches.
> 
> - invoke vhost_dev init repeatedly for # of queues given, unless
>   something wrong happened, which basically means the backend
>   can not support such # of queues; we then quit.
> 
>   We could, as you suggested, add an another message to query
>   the max # queues the backend support. However, judging we have
>   to check the return value of setting up a single queue pair,
>   which already gives feedback when the backed is not able to
>   support requested # of queues, we could save such message,
>   though it's easy to implement :)

Problem is, we only setup queues when device is started,
that is when guest is running.

Doing this at connect would mean we don't start the VM
that we can't then support.

> > 
> > 2. each message (e.g. set memory table) is sent multiple times,
> >    on the same socket.
> 
> Yeah, for there is a single socket opening there, it's not necessary
> to send messages like SET_MEM_TABLE multiple times. But for other
> messages that relate to to a specific vring, we have to send N times,
> don't we?

We need to set up each vring, sure.


> So, I'm wondering could we categorize the message in two types: vring
> specific and none-vring specific. For vring specific, we send it N
> times, with the vhost_dev->vq_index telling which one queue pair
> we have interest.
> 
> For none-vring specific, we just send it once for first queue pair
> (vhost_dev->queue == 0), just like what we did for tap: we launch
> qemu-ifup/down script only for the first queue pair.

Sounds reasonable. Make this all internal to vhost user:
no need for common vhost code to know about this distinction.

> Comments? (And sorry if I made some silly comments, as I'm pretty
> new to this community, say just have read about 2 weeks code).
> 
> 	--yliu
> 
> > 
> > 
> > 
> > >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > >                          NetClientState *peer)
> > >  {
> > > +    uint32_t queues;
> > >      const NetdevVhostUserOptions *vhost_user_opts;
> > >      CharDriverState *chr;
> > >  
> > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > >          return -1;
> > >      }
> > >  
> > > +    /* number of queues for multiqueue */
> > > +    if (vhost_user_opts->has_queues) {
> > > +        queues = vhost_user_opts->queues;
> > > +    } else {
> > > +        queues = 1;
> > > +    }
> > >  
> > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
> > >  }
> > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > index f97ffa1..51e40ce 100644
> > > --- a/qapi-schema.json
> > > +++ b/qapi-schema.json
> > > @@ -2444,12 +2444,16 @@
> > >  #
> > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
> > >  #
> > > +# @queues: #optional number of queues to be created for multiqueue vhost-user
> > > +#          (default: 1) (Since 2.5)
> > > +#
> > >  # Since 2.1
> > >  ##
> > >  { 'struct': 'NetdevVhostUserOptions',
> > >    'data': {
> > >      'chardev':        'str',
> > > -    '*vhostforce':    'bool' } }
> > > +    '*vhostforce':    'bool',
> > > +    '*queues':        'uint32' } }
> > >  
> > >  ##
> > >  # @NetClientOptions
> > > diff --git a/qemu-options.hx b/qemu-options.hx
> > > index ec356f6..dad035e 100644
> > > --- a/qemu-options.hx
> > > +++ b/qemu-options.hx
> > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
> > >  netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
> > >  required hub automatically.
> > >  
> > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > >  
> > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
> > >  be a unix domain socket backed one. The vhost-user uses a specifically defined
> > >  protocol to pass vhost ioctl replacement messages to an application on the other
> > >  end of the socket. On non-MSIX guests, the feature can be forced with
> > > -@var{vhostforce}.
> > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> > > +be created for multiqueue vhost-user.
> > >  
> > >  Example:
> > >  @example
> > > -- 
> > > 1.8.4.2
> > > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-09-01  9:16       ` [Qemu-devel] " Yuanhan Liu
@ 2015-09-01 10:09         ` Michael S. Tsirkin
  2015-09-01 11:42           ` Yuanhan Liu
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-01 10:09 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Tue, Sep 01, 2015 at 05:16:31PM +0800, Yuanhan Liu wrote:
> On Thu, Aug 13, 2015 at 12:22:50PM +0300, Michael S. Tsirkin wrote:
> > On Wed, Aug 12, 2015 at 02:25:42PM +0800, Ouyang Changchun wrote:
> > > This patch is based on top of "vhost-user: protocol updates" series
> > > proposed earlier by Michael S. Tsirkin.
> > > 
> > > Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
> > > actual virt queue, which is similar to attach/detach queue for tap device.
> > > virtio driver on guest doesn't have to use max virt queue pair, it could
> > > enable any number of virt queue ranging from 1 to max virt queue pair.
> > > 
> > > It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.
> > > 
> > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > ---
> > > This is added since v5
> > > 
> > >  docs/specs/vhost-user.txt         | 17 +++++++++++++++++
> > >  hw/net/vhost_net.c                | 18 ++++++++++++++++++
> > >  hw/net/virtio-net.c               |  2 ++
> > >  hw/virtio/vhost-user.c            | 35 +++++++++++++++++++++++++++++++++--
> > >  include/hw/virtio/vhost-backend.h |  2 ++
> > >  include/net/vhost_net.h           |  1 +
> > >  6 files changed, 73 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > > index 9390f89..cca3e5b 100644
> > > --- a/docs/specs/vhost-user.txt
> > > +++ b/docs/specs/vhost-user.txt
> > > @@ -135,6 +135,10 @@ As older slaves don't support negotiating protocol features,
> > >  a feature bit was dedicated for this purpose:
> > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > >  
> > > +The Slave uses vring flag to notify the vhost-user whether one virtq is enabled
> > > +or not. This request doesn't require replies:
> > > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > > +
> > >  Multi queue support
> > >  -------------------
> > >  The protocol supports multiple queues by setting all index fields in the sent
> > > @@ -306,3 +310,16 @@ Message types
> > >        Bits (0-7) of the payload contain the vring index. Bit 8 is the
> > >        invalid FD flag. This flag is set when there is no file descriptor
> > >        in the ancillary data.
> > > +
> > > + * VHOST_USER_SET_VRING_FLAG
> > > +
> > > +      Id: 18
> > > +      Equivalent ioctl: N/A
> > > +      Master payload: vring state description
> > > +
> > > +      Set the flag(enable or disable) in the vring, the vhost user backend
> > > +      enable or disable the vring according to state.num. Olny legal if feature
> > > +      bit VHOST_USER_F_PROTOCOL_FEATURES is present in VHOST_USER_GET_FEATURE
> > > +      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
> > > +      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when state.num is
> > > +      1, otherwise, the vring is disabled.
> > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > index 9cd6c05..5fa341c 100644
> > > --- a/hw/net/vhost_net.c
> > > +++ b/hw/net/vhost_net.c
> > > @@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> > >  
> > >      return vhost_net;
> > >  }
> > > +
> > > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > > +{
> > > +    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> > > +        struct vhost_net *net = get_vhost_net(nc);
> > > +        const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > +        if (vhost_ops->vhost_backend_mq_set_vring_flag)
> > > +            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev, enable);
> > > +    }
> > > +
> > > +    return 0;
> > > +}
> > > +
> > >  #else
> > >  struct vhost_net *vhost_net_init(VhostNetOptions *options)
> > >  {
> > > @@ -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> > >  {
> > >      return 0;
> > >  }
> > > +
> > > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > > +{
> > > +    return 0;
> > > +}
> > >  #endif
> > > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> > > index 3af6faf..272b77d 100644
> > > --- a/hw/net/virtio-net.c
> > > +++ b/hw/net/virtio-net.c
> > > @@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
> > >      }
> > >  
> > >      if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> > > +        vhost_set_vring_flag(nc->peer, 1);
> > >          return 0;
> > >      }
> > >  
> > > @@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
> > >      }
> > >  
> > >      if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
> > > +        vhost_set_vring_flag(nc->peer, 0);
> > >          return 0;
> > >      }
> > >  
> > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> > > index fb11d4c..d806ce2 100644
> > > --- a/hw/virtio/vhost-user.c
> > > +++ b/hw/virtio/vhost-user.c
> > > @@ -25,7 +25,8 @@
> > >  
> > >  #define VHOST_MEMORY_MAX_NREGIONS    8
> > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> > > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > > +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
> > >  
> > >  typedef enum VhostUserRequest {
> > >      VHOST_USER_NONE = 0,
> > > @@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
> > >      VHOST_USER_SET_VRING_ERR = 14,
> > >      VHOST_USER_GET_PROTOCOL_FEATURES = 15,
> > >      VHOST_USER_SET_PROTOCOL_FEATURES = 16,
> > > +    VHOST_USER_SET_VRING_FLAG = 18,
> > >      VHOST_USER_MAX
> > >  } VhostUserRequest;
> > >  
> > > @@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
> > >      return 0;
> > >  }
> > >  
> > > +static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned int enable)
> > > +{
> > > +    VhostUserMsg msg = { 0 };
> > > +    int err;
> > > +
> > > +    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> > > +
> > > +    if ((dev->backend_features & ( 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
> > > +        return -1;
> > > +
> > > +    if ((dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
> > > +        return -1;
> > > +
> > > +    msg.request = VHOST_USER_SET_VRING_FLAG;
> > > +    msg.flags = VHOST_USER_VERSION;
> > > +    /* Set the virt queue pair index */
> > > +    msg.state.index = dev->vq_index / 2;
> > 
> > Thinking about this, this means that the index value is specific to virtio net.
> > This seems wrong.
> 
> How about adding a new field queue_index to vhost_dev structure? So that
> we could get rid of it.
> 
> 	--yliu

don't we have it already?

    /* the first virtqueue which would be used by this vhost dev */
    int vq_index;



> > 
> > > +    msg.state.num = enable;
> > > +    msg.size = sizeof msg.state;
> > > +
> > > +    err = vhost_user_write(dev, &msg, NULL, 0);
> > > +    if (err < 0) {
> > > +        return err;
> > > +    }
> > > +
> > > +    return 0;
> > > +}
> > > +
> > >  static int vhost_user_cleanup(struct vhost_dev *dev)
> > >  {
> > >      assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> > > @@ -412,5 +442,6 @@ const VhostOps user_ops = {
> > >          .backend_type = VHOST_BACKEND_TYPE_USER,
> > >          .vhost_call = vhost_user_call,
> > >          .vhost_backend_init = vhost_user_init,
> > > -        .vhost_backend_cleanup = vhost_user_cleanup
> > > +        .vhost_backend_cleanup = vhost_user_cleanup,
> > > +        .vhost_backend_mq_set_vring_flag = vhost_user_set_vring_flag,
> > >          };
> > > diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h
> > > index e472f29..c394147 100644
> > > --- a/include/hw/virtio/vhost-backend.h
> > > +++ b/include/hw/virtio/vhost-backend.h
> > > @@ -24,12 +24,14 @@ typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int request,
> > >               void *arg);
> > >  typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque);
> > >  typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev);
> > > +typedef int (*vhost_backend_mq_set_vring_flag)(struct vhost_dev *dev, unsigned int enable);
> > >  
> > >  typedef struct VhostOps {
> > >      VhostBackendType backend_type;
> > >      vhost_call vhost_call;
> > >      vhost_backend_init vhost_backend_init;
> > >      vhost_backend_cleanup vhost_backend_cleanup;
> > > +    vhost_backend_mq_set_vring_flag vhost_backend_mq_set_vring_flag;
> > >  } VhostOps;
> > >  
> > >  extern const VhostOps user_ops;
> > > diff --git a/include/net/vhost_net.h b/include/net/vhost_net.h
> > > index b1c18a3..9b76548 100644
> > > --- a/include/net/vhost_net.h
> > > +++ b/include/net/vhost_net.h
> > > @@ -29,4 +29,5 @@ bool vhost_net_virtqueue_pending(VHostNetState *net, int n);
> > >  void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
> > >                                int idx, bool mask);
> > >  VHostNetState *get_vhost_net(NetClientState *nc);
> > > +int vhost_set_vring_flag(NetClientState * nc, unsigned int enable);
> > >  #endif
> > > -- 
> > > 1.8.4.2
> > > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue
  2015-09-01 10:09         ` Michael S. Tsirkin
@ 2015-09-01 11:42           ` Yuanhan Liu
  0 siblings, 0 replies; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01 11:42 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Tue, Sep 01, 2015 at 01:09:15PM +0300, Michael S. Tsirkin wrote:
> On Tue, Sep 01, 2015 at 05:16:31PM +0800, Yuanhan Liu wrote:
> > On Thu, Aug 13, 2015 at 12:22:50PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Aug 12, 2015 at 02:25:42PM +0800, Ouyang Changchun wrote:
> > > > This patch is based on top of "vhost-user: protocol updates" series
> > > > proposed earlier by Michael S. Tsirkin.
> > > > 
> > > > Use new message VHOST_USER_SET_VRING_FLAG to enable and disable an
> > > > actual virt queue, which is similar to attach/detach queue for tap device.
> > > > virtio driver on guest doesn't have to use max virt queue pair, it could
> > > > enable any number of virt queue ranging from 1 to max virt queue pair.
> > > > 
> > > > It requires that VHOST_USER_F_PROTOCOL_FEATURES is present.
> > > > 
> > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > ---
> > > > This is added since v5
> > > > 
> > > >  docs/specs/vhost-user.txt         | 17 +++++++++++++++++
> > > >  hw/net/vhost_net.c                | 18 ++++++++++++++++++
> > > >  hw/net/virtio-net.c               |  2 ++
> > > >  hw/virtio/vhost-user.c            | 35 +++++++++++++++++++++++++++++++++--
> > > >  include/hw/virtio/vhost-backend.h |  2 ++
> > > >  include/net/vhost_net.h           |  1 +
> > > >  6 files changed, 73 insertions(+), 2 deletions(-)
> > > > 
> > > > diff --git a/docs/specs/vhost-user.txt b/docs/specs/vhost-user.txt
> > > > index 9390f89..cca3e5b 100644
> > > > --- a/docs/specs/vhost-user.txt
> > > > +++ b/docs/specs/vhost-user.txt
> > > > @@ -135,6 +135,10 @@ As older slaves don't support negotiating protocol features,
> > > >  a feature bit was dedicated for this purpose:
> > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > >  
> > > > +The Slave uses vring flag to notify the vhost-user whether one virtq is enabled
> > > > +or not. This request doesn't require replies:
> > > > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > > > +
> > > >  Multi queue support
> > > >  -------------------
> > > >  The protocol supports multiple queues by setting all index fields in the sent
> > > > @@ -306,3 +310,16 @@ Message types
> > > >        Bits (0-7) of the payload contain the vring index. Bit 8 is the
> > > >        invalid FD flag. This flag is set when there is no file descriptor
> > > >        in the ancillary data.
> > > > +
> > > > + * VHOST_USER_SET_VRING_FLAG
> > > > +
> > > > +      Id: 18
> > > > +      Equivalent ioctl: N/A
> > > > +      Master payload: vring state description
> > > > +
> > > > +      Set the flag(enable or disable) in the vring, the vhost user backend
> > > > +      enable or disable the vring according to state.num. Olny legal if feature
> > > > +      bit VHOST_USER_F_PROTOCOL_FEATURES is present in VHOST_USER_GET_FEATURE
> > > > +      and feature bit VHOST_USER_PROTOCOL_F_VRING_FLAG is present in
> > > > +      VHOST_USER_GET_PROTOCOL_FEATURES. The vring is enabled when state.num is
> > > > +      1, otherwise, the vring is disabled.
> > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > index 9cd6c05..5fa341c 100644
> > > > --- a/hw/net/vhost_net.c
> > > > +++ b/hw/net/vhost_net.c
> > > > @@ -405,6 +405,19 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> > > >  
> > > >      return vhost_net;
> > > >  }
> > > > +
> > > > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > > > +{
> > > > +    if (nc->info->type == NET_CLIENT_OPTIONS_KIND_VHOST_USER) {
> > > > +        struct vhost_net *net = get_vhost_net(nc);
> > > > +        const VhostOps *vhost_ops = net->dev.vhost_ops;
> > > > +        if (vhost_ops->vhost_backend_mq_set_vring_flag)
> > > > +            return vhost_ops->vhost_backend_mq_set_vring_flag(&net->dev, enable);
> > > > +    }
> > > > +
> > > > +    return 0;
> > > > +}
> > > > +
> > > >  #else
> > > >  struct vhost_net *vhost_net_init(VhostNetOptions *options)
> > > >  {
> > > > @@ -455,4 +468,9 @@ VHostNetState *get_vhost_net(NetClientState *nc)
> > > >  {
> > > >      return 0;
> > > >  }
> > > > +
> > > > +int vhost_set_vring_flag(NetClientState *nc, unsigned int enable)
> > > > +{
> > > > +    return 0;
> > > > +}
> > > >  #endif
> > > > diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
> > > > index 3af6faf..272b77d 100644
> > > > --- a/hw/net/virtio-net.c
> > > > +++ b/hw/net/virtio-net.c
> > > > @@ -396,6 +396,7 @@ static int peer_attach(VirtIONet *n, int index)
> > > >      }
> > > >  
> > > >      if (nc->peer->info->type != NET_CLIENT_OPTIONS_KIND_TAP) {
> > > > +        vhost_set_vring_flag(nc->peer, 1);
> > > >          return 0;
> > > >      }
> > > >  
> > > > @@ -411,6 +412,7 @@ static int peer_detach(VirtIONet *n, int index)
> > > >      }
> > > >  
> > > >      if (nc->peer->info->type !=  NET_CLIENT_OPTIONS_KIND_TAP) {
> > > > +        vhost_set_vring_flag(nc->peer, 0);
> > > >          return 0;
> > > >      }
> > > >  
> > > > diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
> > > > index fb11d4c..d806ce2 100644
> > > > --- a/hw/virtio/vhost-user.c
> > > > +++ b/hw/virtio/vhost-user.c
> > > > @@ -25,7 +25,8 @@
> > > >  
> > > >  #define VHOST_MEMORY_MAX_NREGIONS    8
> > > >  #define VHOST_USER_F_PROTOCOL_FEATURES 30
> > > > -#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x0ULL
> > > > +#define VHOST_USER_PROTOCOL_F_VRING_FLAG 2
> > > > +#define VHOST_USER_PROTOCOL_FEATURE_MASK 0x7ULL
> > > >  
> > > >  typedef enum VhostUserRequest {
> > > >      VHOST_USER_NONE = 0,
> > > > @@ -45,6 +46,7 @@ typedef enum VhostUserRequest {
> > > >      VHOST_USER_SET_VRING_ERR = 14,
> > > >      VHOST_USER_GET_PROTOCOL_FEATURES = 15,
> > > >      VHOST_USER_SET_PROTOCOL_FEATURES = 16,
> > > > +    VHOST_USER_SET_VRING_FLAG = 18,
> > > >      VHOST_USER_MAX
> > > >  } VhostUserRequest;
> > > >  
> > > > @@ -399,6 +401,34 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque)
> > > >      return 0;
> > > >  }
> > > >  
> > > > +static int vhost_user_set_vring_flag(struct vhost_dev *dev, unsigned int enable)
> > > > +{
> > > > +    VhostUserMsg msg = { 0 };
> > > > +    int err;
> > > > +
> > > > +    assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER);
> > > > +
> > > > +    if ((dev->backend_features & ( 1ULL << VHOST_USER_F_PROTOCOL_FEATURES)) == 0)
> > > > +        return -1;
> > > > +
> > > > +    if ((dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_VRING_FLAG)) == 0)
> > > > +        return -1;
> > > > +
> > > > +    msg.request = VHOST_USER_SET_VRING_FLAG;
> > > > +    msg.flags = VHOST_USER_VERSION;
> > > > +    /* Set the virt queue pair index */
> > > > +    msg.state.index = dev->vq_index / 2;
> > > 
> > > Thinking about this, this means that the index value is specific to virtio net.
> > > This seems wrong.
> > 
> > How about adding a new field queue_index to vhost_dev structure? So that
> > we could get rid of it.
> > 
> > 	--yliu
> 
> don't we have it already?
> 
>     /* the first virtqueue which would be used by this vhost dev */
>     int vq_index;

Here queue_index is meant to the index of queue pair, while vq_index is
index of virtio net queue, which simply equals to 2 * queue_index.

Then, maybe we could do as Changchun suggested:

    msg.state.index = dev->vp_index;

So that we could get rid of the '/2' hack(btw, is that what you worried
about?), and let the backend do the virtio queue index to queue pair index 
convertion, aka, divide by 2.

	--yliu

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01 10:07         ` Michael S. Tsirkin
@ 2015-09-01 12:15           ` Yuanhan Liu
  2015-09-01 14:10             ` Michael S. Tsirkin
  0 siblings, 1 reply; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01 12:15 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Tue, Sep 01, 2015 at 01:07:11PM +0300, Michael S. Tsirkin wrote:
> On Tue, Sep 01, 2015 at 05:13:50PM +0800, Yuanhan Liu wrote:
> > On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > Based on patch by Nikolay Nikolaev:
> > > > Vhost-user will implement the multi queue support in a similar way
> > > > to what vhost already has - a separate thread for each queue.
> > > > To enable the multi queue functionality - a new command line parameter
> > > > "queues" is introduced for the vhost-user netdev.
> > > > 
> > > > The RESET_OWNER change is based on commit:
> > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > If it is reverted, the patch need update for it accordingly.
> > > > 
> > > > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > [snip...]
> > > > @@ -198,7 +203,7 @@ Message types
> > > >  
> > > >        Id: 4
> > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > -      Master payload: N/A
> > > > +      Master payload: vring state description
> > > >  
> > > >        Issued when a new connection is about to be closed. The Master will no
> > > >        longer own this connection (and will usually close it).
> > > 
> > > This is an interface change, isn't it?
> > > We can't make it unconditionally, need to make it dependent
> > > on a protocol flag.
> > 
> > Hi Michael,
> > 
> > I'm wondering why we need a payload here, as we don't do that for
> > VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
> > connect is about to be close doesn't make sense to me. Instead,
> > we should clean up all queue pair when VHOST_RESET_OWNER message
> > is received, right?
> 
> We really should rename VHOST_RESET_OWNER to VHOST_RESET_DEVICE.

Yeah, second that.

BTW, can we simply do the name convertion, just changing VHOST_RESET_OWNER
to VHOST_RESET_DEVICE(or VHOST_STOP_DEVICE). I guess it's doable in
theory as far as we don't change the number. I somehow feel it's not a
good practice.

Maybe we could make it as a new vhost message, and mark the old one
as obsolete? That doesn't sound perfect, either, as it reserves a number
for a message we will not use any more.

Also, we may rename VHOST_SET_OWNER to VHOST_INIT_DEVICE?

> And I agree, I don't think it needs a payload.

Good to know.

> 
> 
> > > 
> > > 
> > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > index 1f25cb3..9cd6c05 100644
> > > > --- a/hw/net/vhost_net.c
> > > > +++ b/hw/net/vhost_net.c
> > [snip...]
> > > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > > -                               const char *name, CharDriverState *chr)
> > > > +                               const char *name, CharDriverState *chr,
> > > > +                               uint32_t queues)
> > > >  {
> > > >      NetClientState *nc;
> > > >      VhostUserState *s;
> > > > +    int i;
> > > >  
> > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > > > +    for (i = 0; i < queues; i++) {
> > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > > >  
> > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > -             chr->label);
> > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > > +                 i, chr->label);
> > > >  
> > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > >  
> > > > -    /* We don't provide a receive callback */
> > > > -    s->nc.receive_disabled = 1;
> > > > -    s->chr = chr;
> > > > -
> > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > > +        /* We don't provide a receive callback */
> > > > +        s->nc.receive_disabled = 1;
> > > > +        s->chr = chr;
> > > > +        s->nc.queue_index = i;
> > > >  
> > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > > +    }
> > > >      return 0;
> > > >  }
> > > >  
> > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
> > > 
> > > 
> > > There are two problems here:
> > > 
> > > 1. we don't really know that the backend
> > >    is able to support the requested number of queues.
> > >    If not, everything will fail, silently.
> > >    A new message to query the # of queues could help, though
> > >    I'm not sure what can be done on failure. Fail connection?
> > 
> > What I'm thinking is we may do:
> > 
> > - introduce a feature flag, for indicating we support MQ or not.
> > 
> >   We query this flag only when # of queues given is > 1. We exit
> >   if it not matches.
> > 
> > - invoke vhost_dev init repeatedly for # of queues given, unless
> >   something wrong happened, which basically means the backend
> >   can not support such # of queues; we then quit.
> > 
> >   We could, as you suggested, add an another message to query
> >   the max # queues the backend support. However, judging we have
> >   to check the return value of setting up a single queue pair,
> >   which already gives feedback when the backed is not able to
> >   support requested # of queues, we could save such message,
> >   though it's easy to implement :)
> 
> Problem is, we only setup queues when device is started,
> that is when guest is running.

So we couldn't simply invoke 'exit()', right?

> 
> Doing this at connect would mean we don't start the VM
> that we can't then support.

Sorry, I'm a bit confused then. You just said that we setup queues
when guest is running, but now you were saying that VM hasn't been
started yet at connect time. As far as I know, we setup queues when
the socket is connected. So, isn't it contradictory in your sayings?

> 
> > > 
> > > 2. each message (e.g. set memory table) is sent multiple times,
> > >    on the same socket.
> > 
> > Yeah, for there is a single socket opening there, it's not necessary
> > to send messages like SET_MEM_TABLE multiple times. But for other
> > messages that relate to to a specific vring, we have to send N times,
> > don't we?
> 
> We need to set up each vring, sure.
> 
> 
> > So, I'm wondering could we categorize the message in two types: vring
> > specific and none-vring specific. For vring specific, we send it N
> > times, with the vhost_dev->vq_index telling which one queue pair
> > we have interest.
> > 
> > For none-vring specific, we just send it once for first queue pair
> > (vhost_dev->queue == 0), just like what we did for tap: we launch
> > qemu-ifup/down script only for the first queue pair.
> 
> Sounds reasonable. Make this all internal to vhost user:
> no need for common vhost code to know about this distinction.

Good to know and I'll keep it in mind.

Thanks for your comments.


	--yliu
> 
> > Comments? (And sorry if I made some silly comments, as I'm pretty
> > new to this community, say just have read about 2 weeks code).
> > 
> > 	--yliu
> > 
> > > 
> > > 
> > > 
> > > >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > > >                          NetClientState *peer)
> > > >  {
> > > > +    uint32_t queues;
> > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > >      CharDriverState *chr;
> > > >  
> > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > > >          return -1;
> > > >      }
> > > >  
> > > > +    /* number of queues for multiqueue */
> > > > +    if (vhost_user_opts->has_queues) {
> > > > +        queues = vhost_user_opts->queues;
> > > > +    } else {
> > > > +        queues = 1;
> > > > +    }
> > > >  
> > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
> > > >  }
> > > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > > index f97ffa1..51e40ce 100644
> > > > --- a/qapi-schema.json
> > > > +++ b/qapi-schema.json
> > > > @@ -2444,12 +2444,16 @@
> > > >  #
> > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
> > > >  #
> > > > +# @queues: #optional number of queues to be created for multiqueue vhost-user
> > > > +#          (default: 1) (Since 2.5)
> > > > +#
> > > >  # Since 2.1
> > > >  ##
> > > >  { 'struct': 'NetdevVhostUserOptions',
> > > >    'data': {
> > > >      'chardev':        'str',
> > > > -    '*vhostforce':    'bool' } }
> > > > +    '*vhostforce':    'bool',
> > > > +    '*queues':        'uint32' } }
> > > >  
> > > >  ##
> > > >  # @NetClientOptions
> > > > diff --git a/qemu-options.hx b/qemu-options.hx
> > > > index ec356f6..dad035e 100644
> > > > --- a/qemu-options.hx
> > > > +++ b/qemu-options.hx
> > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
> > > >  netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
> > > >  required hub automatically.
> > > >  
> > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > >  
> > > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
> > > >  be a unix domain socket backed one. The vhost-user uses a specifically defined
> > > >  protocol to pass vhost ioctl replacement messages to an application on the other
> > > >  end of the socket. On non-MSIX guests, the feature can be forced with
> > > > -@var{vhostforce}.
> > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> > > > +be created for multiqueue vhost-user.
> > > >  
> > > >  Example:
> > > >  @example
> > > > -- 
> > > > 1.8.4.2
> > > > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [snabb-devel] Re: [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01  9:41                     ` Michael S. Tsirkin
@ 2015-09-01 12:16                       ` Yuanhan Liu
  0 siblings, 0 replies; 44+ messages in thread
From: Yuanhan Liu @ 2015-09-01 12:16 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun

On Tue, Sep 01, 2015 at 12:41:49PM +0300, Michael S. Tsirkin wrote:
> On Tue, Sep 01, 2015 at 05:20:06PM +0800, Yuanhan Liu wrote:
> > On Mon, Aug 31, 2015 at 02:30:06PM +0300, Michael S. Tsirkin wrote:
> > [snip..] 
> > > > Then how about the other case:
> > > > When startup the vhost backend, user specify 8 queues, like:
> > > > Vhost-user ...  -queues 8      # Y=8
> > > > When startup the guest, user specify 4 queues, like:
> > > > Qemu-kvm ... -queues 4      # X=4
> > > > 
> > > > Vhost backend CAN support the queues number as much as the guest/qemu requires,
> > > > And qemu don't want enable all of them(8 in the case), just part of them(only 4 from 8).
> > > > Will qemu exit or go forward(of course with 4 queues)? 
> > > 
> > > I think it must go forward since guest does not have to
> > > configure all queues anyway - and that's built in to virtio spec.
> > > 
> > > Note that # of queues in actual use in fact changes dynamically
> > > too, without restaring the device.
> > 
> > May I know how do you do that? I mean, is there a public interface, like
> > by some commands? Or, by sending vhost messages?
> > 
> > 	--yliu
> 
> Using ethtool within guest. In fact, guests boot with a single queue,
> you need to use ethtool to enable mq, specifying the # of queues.

Thanks for the info.

	--yliu

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01 12:15           ` Yuanhan Liu
@ 2015-09-01 14:10             ` Michael S. Tsirkin
  2015-09-02  5:45               ` Ouyang, Changchun
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-01 14:10 UTC (permalink / raw)
  To: Yuanhan Liu
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Tue, Sep 01, 2015 at 08:15:15PM +0800, Yuanhan Liu wrote:
> On Tue, Sep 01, 2015 at 01:07:11PM +0300, Michael S. Tsirkin wrote:
> > On Tue, Sep 01, 2015 at 05:13:50PM +0800, Yuanhan Liu wrote:
> > > On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > Based on patch by Nikolay Nikolaev:
> > > > > Vhost-user will implement the multi queue support in a similar way
> > > > > to what vhost already has - a separate thread for each queue.
> > > > > To enable the multi queue functionality - a new command line parameter
> > > > > "queues" is introduced for the vhost-user netdev.
> > > > > 
> > > > > The RESET_OWNER change is based on commit:
> > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > If it is reverted, the patch need update for it accordingly.
> > > > > 
> > > > > Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > [snip...]
> > > > > @@ -198,7 +203,7 @@ Message types
> > > > >  
> > > > >        Id: 4
> > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > -      Master payload: N/A
> > > > > +      Master payload: vring state description
> > > > >  
> > > > >        Issued when a new connection is about to be closed. The Master will no
> > > > >        longer own this connection (and will usually close it).
> > > > 
> > > > This is an interface change, isn't it?
> > > > We can't make it unconditionally, need to make it dependent
> > > > on a protocol flag.
> > > 
> > > Hi Michael,
> > > 
> > > I'm wondering why we need a payload here, as we don't do that for
> > > VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
> > > connect is about to be close doesn't make sense to me. Instead,
> > > we should clean up all queue pair when VHOST_RESET_OWNER message
> > > is received, right?
> > 
> > We really should rename VHOST_RESET_OWNER to VHOST_RESET_DEVICE.
> 
> Yeah, second that.
> 
> BTW, can we simply do the name convertion, just changing VHOST_RESET_OWNER
> to VHOST_RESET_DEVICE(or VHOST_STOP_DEVICE). I guess it's doable in
> theory as far as we don't change the number. I somehow feel it's not a
> good practice.

I think just renaming is fine, we are not changing the protocol
at all.

> Maybe we could make it as a new vhost message, and mark the old one
> as obsolete? That doesn't sound perfect, either, as it reserves a number
> for a message we will not use any more.
> 
> Also, we may rename VHOST_SET_OWNER to VHOST_INIT_DEVICE?

I think VHOST_SET_OWNER specified who's the master?

> > And I agree, I don't think it needs a payload.
> 
> Good to know.
> 
> > 
> > 
> > > > 
> > > > 
> > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
> > > > > index 1f25cb3..9cd6c05 100644
> > > > > --- a/hw/net/vhost_net.c
> > > > > +++ b/hw/net/vhost_net.c
> > > [snip...]
> > > > >  static int net_vhost_user_init(NetClientState *peer, const char *device,
> > > > > -                               const char *name, CharDriverState *chr)
> > > > > +                               const char *name, CharDriverState *chr,
> > > > > +                               uint32_t queues)
> > > > >  {
> > > > >      NetClientState *nc;
> > > > >      VhostUserState *s;
> > > > > +    int i;
> > > > >  
> > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > > > > +    for (i = 0; i < queues; i++) {
> > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
> > > > >  
> > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > -             chr->label);
> > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
> > > > > +                 i, chr->label);
> > > > >  
> > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > >  
> > > > > -    /* We don't provide a receive callback */
> > > > > -    s->nc.receive_disabled = 1;
> > > > > -    s->chr = chr;
> > > > > -
> > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > > > +        /* We don't provide a receive callback */
> > > > > +        s->nc.receive_disabled = 1;
> > > > > +        s->chr = chr;
> > > > > +        s->nc.queue_index = i;
> > > > >  
> > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL, net_vhost_user_event, s);
> > > > > +    }
> > > > >      return 0;
> > > > >  }
> > > > >  
> > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts *opts, void *opaque)
> > > > 
> > > > 
> > > > There are two problems here:
> > > > 
> > > > 1. we don't really know that the backend
> > > >    is able to support the requested number of queues.
> > > >    If not, everything will fail, silently.
> > > >    A new message to query the # of queues could help, though
> > > >    I'm not sure what can be done on failure. Fail connection?
> > > 
> > > What I'm thinking is we may do:
> > > 
> > > - introduce a feature flag, for indicating we support MQ or not.
> > > 
> > >   We query this flag only when # of queues given is > 1. We exit
> > >   if it not matches.
> > > 
> > > - invoke vhost_dev init repeatedly for # of queues given, unless
> > >   something wrong happened, which basically means the backend
> > >   can not support such # of queues; we then quit.
> > > 
> > >   We could, as you suggested, add an another message to query
> > >   the max # queues the backend support. However, judging we have
> > >   to check the return value of setting up a single queue pair,
> > >   which already gives feedback when the backed is not able to
> > >   support requested # of queues, we could save such message,
> > >   though it's easy to implement :)
> > 
> > Problem is, we only setup queues when device is started,
> > that is when guest is running.
> 
> So we couldn't simply invoke 'exit()', right?
> 
> > 
> > Doing this at connect would mean we don't start the VM
> > that we can't then support.
> 
> Sorry, I'm a bit confused then. You just said that we setup queues
> when guest is running, but now you were saying that VM hasn't been
> started yet at connect time. As far as I know, we setup queues when
> the socket is connected. So, isn't it contradictory in your sayings?
> 
> > 
> > > > 
> > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > >    on the same socket.
> > > 
> > > Yeah, for there is a single socket opening there, it's not necessary
> > > to send messages like SET_MEM_TABLE multiple times. But for other
> > > messages that relate to to a specific vring, we have to send N times,
> > > don't we?
> > 
> > We need to set up each vring, sure.
> > 
> > 
> > > So, I'm wondering could we categorize the message in two types: vring
> > > specific and none-vring specific. For vring specific, we send it N
> > > times, with the vhost_dev->vq_index telling which one queue pair
> > > we have interest.
> > > 
> > > For none-vring specific, we just send it once for first queue pair
> > > (vhost_dev->queue == 0), just like what we did for tap: we launch
> > > qemu-ifup/down script only for the first queue pair.
> > 
> > Sounds reasonable. Make this all internal to vhost user:
> > no need for common vhost code to know about this distinction.
> 
> Good to know and I'll keep it in mind.
> 
> Thanks for your comments.
> 
> 
> 	--yliu
> > 
> > > Comments? (And sorry if I made some silly comments, as I'm pretty
> > > new to this community, say just have read about 2 weeks code).
> > > 
> > > 	--yliu
> > > 
> > > > 
> > > > 
> > > > 
> > > > >  int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > > > >                          NetClientState *peer)
> > > > >  {
> > > > > +    uint32_t queues;
> > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > >      CharDriverState *chr;
> > > > >  
> > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const NetClientOptions *opts, const char *name,
> > > > >          return -1;
> > > > >      }
> > > > >  
> > > > > +    /* number of queues for multiqueue */
> > > > > +    if (vhost_user_opts->has_queues) {
> > > > > +        queues = vhost_user_opts->queues;
> > > > > +    } else {
> > > > > +        queues = 1;
> > > > > +    }
> > > > >  
> > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr, queues);
> > > > >  }
> > > > > diff --git a/qapi-schema.json b/qapi-schema.json
> > > > > index f97ffa1..51e40ce 100644
> > > > > --- a/qapi-schema.json
> > > > > +++ b/qapi-schema.json
> > > > > @@ -2444,12 +2444,16 @@
> > > > >  #
> > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests (default: false).
> > > > >  #
> > > > > +# @queues: #optional number of queues to be created for multiqueue vhost-user
> > > > > +#          (default: 1) (Since 2.5)
> > > > > +#
> > > > >  # Since 2.1
> > > > >  ##
> > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > >    'data': {
> > > > >      'chardev':        'str',
> > > > > -    '*vhostforce':    'bool' } }
> > > > > +    '*vhostforce':    'bool',
> > > > > +    '*queues':        'uint32' } }
> > > > >  
> > > > >  ##
> > > > >  # @NetClientOptions
> > > > > diff --git a/qemu-options.hx b/qemu-options.hx
> > > > > index ec356f6..dad035e 100644
> > > > > --- a/qemu-options.hx
> > > > > +++ b/qemu-options.hx
> > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a NIC to a QEMU "vlan" instead of a single
> > > > >  netdev.  @code{-net} and @code{-device} with parameter @option{vlan} create the
> > > > >  required hub automatically.
> > > > >  
> > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > +@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > >  
> > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}. The chardev should
> > > > >  be a unix domain socket backed one. The vhost-user uses a specifically defined
> > > > >  protocol to pass vhost ioctl replacement messages to an application on the other
> > > > >  end of the socket. On non-MSIX guests, the feature can be forced with
> > > > > -@var{vhostforce}.
> > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number of queues to
> > > > > +be created for multiqueue vhost-user.
> > > > >  
> > > > >  Example:
> > > > >  @example
> > > > > -- 
> > > > > 1.8.4.2
> > > > > 

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-01 14:10             ` Michael S. Tsirkin
@ 2015-09-02  5:45               ` Ouyang, Changchun
  2015-09-02 12:10                 ` Michael S. Tsirkin
  0 siblings, 1 reply; 44+ messages in thread
From: Ouyang, Changchun @ 2015-09-02  5:45 UTC (permalink / raw)
  To: Michael S. Tsirkin, Yuanhan Liu
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, Long,
	Thomas, Ouyang, Changchun



> -----Original Message-----
> From: Michael S. Tsirkin [mailto:mst@redhat.com]
> Sent: Tuesday, September 1, 2015 10:10 PM
> To: Yuanhan Liu
> Cc: snabb-devel@googlegroups.com; thibaut.collet@6wind.com; qemu-
> devel@nongnu.org; n.nikolaev@virtualopensystems.com; luke@snabb.co;
> Long, Thomas; Ouyang, Changchun
> Subject: Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue
> support
> 
> On Tue, Sep 01, 2015 at 08:15:15PM +0800, Yuanhan Liu wrote:
> > On Tue, Sep 01, 2015 at 01:07:11PM +0300, Michael S. Tsirkin wrote:
> > > On Tue, Sep 01, 2015 at 05:13:50PM +0800, Yuanhan Liu wrote:
> > > > On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> > > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > > Based on patch by Nikolay Nikolaev:
> > > > > > Vhost-user will implement the multi queue support in a similar
> > > > > > way to what vhost already has - a separate thread for each queue.
> > > > > > To enable the multi queue functionality - a new command line
> > > > > > parameter "queues" is introduced for the vhost-user netdev.
> > > > > >
> > > > > > The RESET_OWNER change is based on commit:
> > > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > > If it is reverted, the patch need update for it accordingly.
> > > > > >
> > > > > > Signed-off-by: Nikolay Nikolaev
> > > > > > <n.nikolaev@virtualopensystems.com>
> > > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > [snip...]
> > > > > > @@ -198,7 +203,7 @@ Message types
> > > > > >
> > > > > >        Id: 4
> > > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > > -      Master payload: N/A
> > > > > > +      Master payload: vring state description
> > > > > >
> > > > > >        Issued when a new connection is about to be closed. The Master
> will no
> > > > > >        longer own this connection (and will usually close it).
> > > > >
> > > > > This is an interface change, isn't it?
> > > > > We can't make it unconditionally, need to make it dependent on a
> > > > > protocol flag.
> > > >
> > > > Hi Michael,
> > > >
> > > > I'm wondering why we need a payload here, as we don't do that for
> > > > VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
> > > > connect is about to be close doesn't make sense to me. Instead, we
> > > > should clean up all queue pair when VHOST_RESET_OWNER message is
> > > > received, right?
> > >
> > > We really should rename VHOST_RESET_OWNER to
> VHOST_RESET_DEVICE.
> >
> > Yeah, second that.
> >
> > BTW, can we simply do the name convertion, just changing
> > VHOST_RESET_OWNER to VHOST_RESET_DEVICE(or VHOST_STOP_DEVICE).
> I guess
> > it's doable in theory as far as we don't change the number. I somehow
> > feel it's not a good practice.
> 
> I think just renaming is fine, we are not changing the protocol at all.

Agree, till now, VHOST_RESET_OWNER is not used pretty much, so no backward compatibility issue.
Renaming it is enough.

> 
> > Maybe we could make it as a new vhost message, and mark the old one as
> > obsolete? That doesn't sound perfect, either, as it reserves a number
> > for a message we will not use any more.
> >
> > Also, we may rename VHOST_SET_OWNER to VHOST_INIT_DEVICE?
> 
> I think VHOST_SET_OWNER specified who's the master?
> 

I think VHOST_SET_OWNER is also the message for socket, not for each vring.

> > > And I agree, I don't think it needs a payload.
> >
> > Good to know.
> >
> > >
> > >
> > > > >
> > > > >
> > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > > > 1f25cb3..9cd6c05 100644
> > > > > > --- a/hw/net/vhost_net.c
> > > > > > +++ b/hw/net/vhost_net.c
> > > > [snip...]
> > > > > >  static int net_vhost_user_init(NetClientState *peer, const char
> *device,
> > > > > > -                               const char *name, CharDriverState *chr)
> > > > > > +                               const char *name, CharDriverState *chr,
> > > > > > +                               uint32_t queues)
> > > > > >  {
> > > > > >      NetClientState *nc;
> > > > > >      VhostUserState *s;
> > > > > > +    int i;
> > > > > >
> > > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> name);
> > > > > > +    for (i = 0; i < queues; i++) {
> > > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > > > + device, name);
> > > > > >
> > > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > > -             chr->label);
> > > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d
> to %s",
> > > > > > +                 i, chr->label);
> > > > > >
> > > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > >
> > > > > > -    /* We don't provide a receive callback */
> > > > > > -    s->nc.receive_disabled = 1;
> > > > > > -    s->chr = chr;
> > > > > > -
> > > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> net_vhost_user_event, s);
> > > > > > +        /* We don't provide a receive callback */
> > > > > > +        s->nc.receive_disabled = 1;
> > > > > > +        s->chr = chr;
> > > > > > +        s->nc.queue_index = i;
> > > > > >
> > > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> net_vhost_user_event, s);
> > > > > > +    }
> > > > > >      return 0;
> > > > > >  }
> > > > > >
> > > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> > > > > > *opts, void *opaque)
> > > > >
> > > > >
> > > > > There are two problems here:
> > > > >
> > > > > 1. we don't really know that the backend
> > > > >    is able to support the requested number of queues.
> > > > >    If not, everything will fail, silently.
> > > > >    A new message to query the # of queues could help, though
> > > > >    I'm not sure what can be done on failure. Fail connection?
> > > >
> > > > What I'm thinking is we may do:
> > > >
> > > > - introduce a feature flag, for indicating we support MQ or not.
> > > >
> > > >   We query this flag only when # of queues given is > 1. We exit
> > > >   if it not matches.
> > > >
> > > > - invoke vhost_dev init repeatedly for # of queues given, unless
> > > >   something wrong happened, which basically means the backend
> > > >   can not support such # of queues; we then quit.
> > > >
> > > >   We could, as you suggested, add an another message to query
> > > >   the max # queues the backend support. However, judging we have
> > > >   to check the return value of setting up a single queue pair,
> > > >   which already gives feedback when the backed is not able to
> > > >   support requested # of queues, we could save such message,
> > > >   though it's easy to implement :)
> > >
> > > Problem is, we only setup queues when device is started, that is
> > > when guest is running.
> >
> > So we couldn't simply invoke 'exit()', right?
> >
> > >
> > > Doing this at connect would mean we don't start the VM that we can't
> > > then support.
> >
> > Sorry, I'm a bit confused then. You just said that we setup queues
> > when guest is running, but now you were saying that VM hasn't been
> > started yet at connect time. As far as I know, we setup queues when
> > the socket is connected. So, isn't it contradictory in your sayings?
> >
> > >
> > > > >
> > > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > > >    on the same socket.
> > > >
> > > > Yeah, for there is a single socket opening there, it's not
> > > > necessary to send messages like SET_MEM_TABLE multiple times. But
> > > > for other messages that relate to to a specific vring, we have to
> > > > send N times, don't we?
> > >
> > > We need to set up each vring, sure.
> > >
> > >
> > > > So, I'm wondering could we categorize the message in two types:
> > > > vring specific and none-vring specific. For vring specific, we
> > > > send it N times, with the vhost_dev->vq_index telling which one
> > > > queue pair we have interest.
> > > >
> > > > For none-vring specific, we just send it once for first queue pair
> > > > (vhost_dev->queue == 0), just like what we did for tap: we launch
> > > > qemu-ifup/down script only for the first queue pair.
> > >
> > > Sounds reasonable. Make this all internal to vhost user:
> > > no need for common vhost code to know about this distinction.
> >
> > Good to know and I'll keep it in mind.
> >
> > Thanks for your comments.
> >
> >
> > 	--yliu
> > >
> > > > Comments? (And sorry if I made some silly comments, as I'm pretty
> > > > new to this community, say just have read about 2 weeks code).
> > > >
> > > > 	--yliu
> > > >
> > > > >
> > > > >
> > > > >
> > > > > >  int net_init_vhost_user(const NetClientOptions *opts, const char
> *name,
> > > > > >                          NetClientState *peer)  {
> > > > > > +    uint32_t queues;
> > > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > > >      CharDriverState *chr;
> > > > > >
> > > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> NetClientOptions *opts, const char *name,
> > > > > >          return -1;
> > > > > >      }
> > > > > >
> > > > > > +    /* number of queues for multiqueue */
> > > > > > +    if (vhost_user_opts->has_queues) {
> > > > > > +        queues = vhost_user_opts->queues;
> > > > > > +    } else {
> > > > > > +        queues = 1;
> > > > > > +    }
> > > > > >
> > > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > > > + queues);
> > > > > >  }
> > > > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > > > f97ffa1..51e40ce 100644
> > > > > > --- a/qapi-schema.json
> > > > > > +++ b/qapi-schema.json
> > > > > > @@ -2444,12 +2444,16 @@
> > > > > >  #
> > > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests
> (default: false).
> > > > > >  #
> > > > > > +# @queues: #optional number of queues to be created for
> multiqueue vhost-user
> > > > > > +#          (default: 1) (Since 2.5)
> > > > > > +#
> > > > > >  # Since 2.1
> > > > > >  ##
> > > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > > >    'data': {
> > > > > >      'chardev':        'str',
> > > > > > -    '*vhostforce':    'bool' } }
> > > > > > +    '*vhostforce':    'bool',
> > > > > > +    '*queues':        'uint32' } }
> > > > > >
> > > > > >  ##
> > > > > >  # @NetClientOptions
> > > > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > > > ec356f6..dad035e 100644
> > > > > > --- a/qemu-options.hx
> > > > > > +++ b/qemu-options.hx
> > > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a
> > > > > > NIC to a QEMU "vlan" instead of a single  netdev.  @code{-net}
> > > > > > and @code{-device} with parameter @option{vlan} create the
> required hub automatically.
> > > > > >
> > > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > > +@item -netdev
> > > > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > > >
> > > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}.
> > > > > > The chardev should  be a unix domain socket backed one. The
> > > > > > vhost-user uses a specifically defined  protocol to pass vhost
> > > > > > ioctl replacement messages to an application on the other  end
> > > > > > of the socket. On non-MSIX guests, the feature can be forced with -
> @var{vhostforce}.
> > > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number
> > > > > > +of queues to be created for multiqueue vhost-user.
> > > > > >
> > > > > >  Example:
> > > > > >  @example
> > > > > > --
> > > > > > 1.8.4.2
> > > > > >

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-02  5:45               ` Ouyang, Changchun
@ 2015-09-02 12:10                 ` Michael S. Tsirkin
  0 siblings, 0 replies; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-02 12:10 UTC (permalink / raw)
  To: Ouyang, Changchun
  Cc: Yuanhan Liu, snabb-devel, thibaut.collet, qemu-devel, n.nikolaev,
	luke, Long, Thomas

On Wed, Sep 02, 2015 at 05:45:18AM +0000, Ouyang, Changchun wrote:
> 
> 
> > -----Original Message-----
> > From: Michael S. Tsirkin [mailto:mst@redhat.com]
> > Sent: Tuesday, September 1, 2015 10:10 PM
> > To: Yuanhan Liu
> > Cc: snabb-devel@googlegroups.com; thibaut.collet@6wind.com; qemu-
> > devel@nongnu.org; n.nikolaev@virtualopensystems.com; luke@snabb.co;
> > Long, Thomas; Ouyang, Changchun
> > Subject: Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue
> > support
> > 
> > On Tue, Sep 01, 2015 at 08:15:15PM +0800, Yuanhan Liu wrote:
> > > On Tue, Sep 01, 2015 at 01:07:11PM +0300, Michael S. Tsirkin wrote:
> > > > On Tue, Sep 01, 2015 at 05:13:50PM +0800, Yuanhan Liu wrote:
> > > > > On Thu, Aug 13, 2015 at 12:18:38PM +0300, Michael S. Tsirkin wrote:
> > > > > > On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> > > > > > > Based on patch by Nikolay Nikolaev:
> > > > > > > Vhost-user will implement the multi queue support in a similar
> > > > > > > way to what vhost already has - a separate thread for each queue.
> > > > > > > To enable the multi queue functionality - a new command line
> > > > > > > parameter "queues" is introduced for the vhost-user netdev.
> > > > > > >
> > > > > > > The RESET_OWNER change is based on commit:
> > > > > > >    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> > > > > > > If it is reverted, the patch need update for it accordingly.
> > > > > > >
> > > > > > > Signed-off-by: Nikolay Nikolaev
> > > > > > > <n.nikolaev@virtualopensystems.com>
> > > > > > > Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> > > > > [snip...]
> > > > > > > @@ -198,7 +203,7 @@ Message types
> > > > > > >
> > > > > > >        Id: 4
> > > > > > >        Equivalent ioctl: VHOST_RESET_OWNER
> > > > > > > -      Master payload: N/A
> > > > > > > +      Master payload: vring state description
> > > > > > >
> > > > > > >        Issued when a new connection is about to be closed. The Master
> > will no
> > > > > > >        longer own this connection (and will usually close it).
> > > > > >
> > > > > > This is an interface change, isn't it?
> > > > > > We can't make it unconditionally, need to make it dependent on a
> > > > > > protocol flag.
> > > > >
> > > > > Hi Michael,
> > > > >
> > > > > I'm wondering why we need a payload here, as we don't do that for
> > > > > VHOST_SET_OWNER. I mean, stopping one or few queue pairs when a
> > > > > connect is about to be close doesn't make sense to me. Instead, we
> > > > > should clean up all queue pair when VHOST_RESET_OWNER message is
> > > > > received, right?
> > > >
> > > > We really should rename VHOST_RESET_OWNER to
> > VHOST_RESET_DEVICE.
> > >
> > > Yeah, second that.
> > >
> > > BTW, can we simply do the name convertion, just changing
> > > VHOST_RESET_OWNER to VHOST_RESET_DEVICE(or VHOST_STOP_DEVICE).
> > I guess
> > > it's doable in theory as far as we don't change the number. I somehow
> > > feel it's not a good practice.
> > 
> > I think just renaming is fine, we are not changing the protocol at all.
> 
> Agree, till now, VHOST_RESET_OWNER is not used pretty much, so no backward compatibility issue.
> Renaming it is enough.
> 
> > 
> > > Maybe we could make it as a new vhost message, and mark the old one as
> > > obsolete? That doesn't sound perfect, either, as it reserves a number
> > > for a message we will not use any more.
> > >
> > > Also, we may rename VHOST_SET_OWNER to VHOST_INIT_DEVICE?
> > 
> > I think VHOST_SET_OWNER specified who's the master?
> > 
> 
> I think VHOST_SET_OWNER is also the message for socket, not for each vring.

Exactly. Documentation says it sets the sender as the master of the socket.

> > > > And I agree, I don't think it needs a payload.
> > >
> > > Good to know.
> > >
> > > >
> > > >
> > > > > >
> > > > > >
> > > > > > > diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index
> > > > > > > 1f25cb3..9cd6c05 100644
> > > > > > > --- a/hw/net/vhost_net.c
> > > > > > > +++ b/hw/net/vhost_net.c
> > > > > [snip...]
> > > > > > >  static int net_vhost_user_init(NetClientState *peer, const char
> > *device,
> > > > > > > -                               const char *name, CharDriverState *chr)
> > > > > > > +                               const char *name, CharDriverState *chr,
> > > > > > > +                               uint32_t queues)
> > > > > > >  {
> > > > > > >      NetClientState *nc;
> > > > > > >      VhostUserState *s;
> > > > > > > +    int i;
> > > > > > >
> > > > > > > -    nc = qemu_new_net_client(&net_vhost_user_info, peer, device,
> > name);
> > > > > > > +    for (i = 0; i < queues; i++) {
> > > > > > > +        nc = qemu_new_net_client(&net_vhost_user_info, peer,
> > > > > > > + device, name);
> > > > > > >
> > > > > > > -    snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user to %s",
> > > > > > > -             chr->label);
> > > > > > > +        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d
> > to %s",
> > > > > > > +                 i, chr->label);
> > > > > > >
> > > > > > > -    s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > > +        s = DO_UPCAST(VhostUserState, nc, nc);
> > > > > > >
> > > > > > > -    /* We don't provide a receive callback */
> > > > > > > -    s->nc.receive_disabled = 1;
> > > > > > > -    s->chr = chr;
> > > > > > > -
> > > > > > > -    qemu_chr_add_handlers(s->chr, NULL, NULL,
> > net_vhost_user_event, s);
> > > > > > > +        /* We don't provide a receive callback */
> > > > > > > +        s->nc.receive_disabled = 1;
> > > > > > > +        s->chr = chr;
> > > > > > > +        s->nc.queue_index = i;
> > > > > > >
> > > > > > > +        qemu_chr_add_handlers(s->chr, NULL, NULL,
> > net_vhost_user_event, s);
> > > > > > > +    }
> > > > > > >      return 0;
> > > > > > >  }
> > > > > > >
> > > > > > > @@ -225,6 +229,7 @@ static int net_vhost_check_net(QemuOpts
> > > > > > > *opts, void *opaque)
> > > > > >
> > > > > >
> > > > > > There are two problems here:
> > > > > >
> > > > > > 1. we don't really know that the backend
> > > > > >    is able to support the requested number of queues.
> > > > > >    If not, everything will fail, silently.
> > > > > >    A new message to query the # of queues could help, though
> > > > > >    I'm not sure what can be done on failure. Fail connection?
> > > > >
> > > > > What I'm thinking is we may do:
> > > > >
> > > > > - introduce a feature flag, for indicating we support MQ or not.
> > > > >
> > > > >   We query this flag only when # of queues given is > 1. We exit
> > > > >   if it not matches.
> > > > >
> > > > > - invoke vhost_dev init repeatedly for # of queues given, unless
> > > > >   something wrong happened, which basically means the backend
> > > > >   can not support such # of queues; we then quit.
> > > > >
> > > > >   We could, as you suggested, add an another message to query
> > > > >   the max # queues the backend support. However, judging we have
> > > > >   to check the return value of setting up a single queue pair,
> > > > >   which already gives feedback when the backed is not able to
> > > > >   support requested # of queues, we could save such message,
> > > > >   though it's easy to implement :)
> > > >
> > > > Problem is, we only setup queues when device is started, that is
> > > > when guest is running.
> > >
> > > So we couldn't simply invoke 'exit()', right?
> > >
> > > >
> > > > Doing this at connect would mean we don't start the VM that we can't
> > > > then support.
> > >
> > > Sorry, I'm a bit confused then. You just said that we setup queues
> > > when guest is running, but now you were saying that VM hasn't been
> > > started yet at connect time. As far as I know, we setup queues when
> > > the socket is connected. So, isn't it contradictory in your sayings?
> > >
> > > >
> > > > > >
> > > > > > 2. each message (e.g. set memory table) is sent multiple times,
> > > > > >    on the same socket.
> > > > >
> > > > > Yeah, for there is a single socket opening there, it's not
> > > > > necessary to send messages like SET_MEM_TABLE multiple times. But
> > > > > for other messages that relate to to a specific vring, we have to
> > > > > send N times, don't we?
> > > >
> > > > We need to set up each vring, sure.
> > > >
> > > >
> > > > > So, I'm wondering could we categorize the message in two types:
> > > > > vring specific and none-vring specific. For vring specific, we
> > > > > send it N times, with the vhost_dev->vq_index telling which one
> > > > > queue pair we have interest.
> > > > >
> > > > > For none-vring specific, we just send it once for first queue pair
> > > > > (vhost_dev->queue == 0), just like what we did for tap: we launch
> > > > > qemu-ifup/down script only for the first queue pair.
> > > >
> > > > Sounds reasonable. Make this all internal to vhost user:
> > > > no need for common vhost code to know about this distinction.
> > >
> > > Good to know and I'll keep it in mind.
> > >
> > > Thanks for your comments.
> > >
> > >
> > > 	--yliu
> > > >
> > > > > Comments? (And sorry if I made some silly comments, as I'm pretty
> > > > > new to this community, say just have read about 2 weeks code).
> > > > >
> > > > > 	--yliu
> > > > >
> > > > > >
> > > > > >
> > > > > >
> > > > > > >  int net_init_vhost_user(const NetClientOptions *opts, const char
> > *name,
> > > > > > >                          NetClientState *peer)  {
> > > > > > > +    uint32_t queues;
> > > > > > >      const NetdevVhostUserOptions *vhost_user_opts;
> > > > > > >      CharDriverState *chr;
> > > > > > >
> > > > > > > @@ -243,6 +248,12 @@ int net_init_vhost_user(const
> > NetClientOptions *opts, const char *name,
> > > > > > >          return -1;
> > > > > > >      }
> > > > > > >
> > > > > > > +    /* number of queues for multiqueue */
> > > > > > > +    if (vhost_user_opts->has_queues) {
> > > > > > > +        queues = vhost_user_opts->queues;
> > > > > > > +    } else {
> > > > > > > +        queues = 1;
> > > > > > > +    }
> > > > > > >
> > > > > > > -    return net_vhost_user_init(peer, "vhost_user", name, chr);
> > > > > > > +    return net_vhost_user_init(peer, "vhost_user", name, chr,
> > > > > > > + queues);
> > > > > > >  }
> > > > > > > diff --git a/qapi-schema.json b/qapi-schema.json index
> > > > > > > f97ffa1..51e40ce 100644
> > > > > > > --- a/qapi-schema.json
> > > > > > > +++ b/qapi-schema.json
> > > > > > > @@ -2444,12 +2444,16 @@
> > > > > > >  #
> > > > > > >  # @vhostforce: #optional vhost on for non-MSIX virtio guests
> > (default: false).
> > > > > > >  #
> > > > > > > +# @queues: #optional number of queues to be created for
> > multiqueue vhost-user
> > > > > > > +#          (default: 1) (Since 2.5)
> > > > > > > +#
> > > > > > >  # Since 2.1
> > > > > > >  ##
> > > > > > >  { 'struct': 'NetdevVhostUserOptions',
> > > > > > >    'data': {
> > > > > > >      'chardev':        'str',
> > > > > > > -    '*vhostforce':    'bool' } }
> > > > > > > +    '*vhostforce':    'bool',
> > > > > > > +    '*queues':        'uint32' } }
> > > > > > >
> > > > > > >  ##
> > > > > > >  # @NetClientOptions
> > > > > > > diff --git a/qemu-options.hx b/qemu-options.hx index
> > > > > > > ec356f6..dad035e 100644
> > > > > > > --- a/qemu-options.hx
> > > > > > > +++ b/qemu-options.hx
> > > > > > > @@ -1942,13 +1942,14 @@ The hubport netdev lets you connect a
> > > > > > > NIC to a QEMU "vlan" instead of a single  netdev.  @code{-net}
> > > > > > > and @code{-device} with parameter @option{vlan} create the
> > required hub automatically.
> > > > > > >
> > > > > > > -@item -netdev vhost-user,chardev=@var{id}[,vhostforce=on|off]
> > > > > > > +@item -netdev
> > > > > > > +vhost-user,chardev=@var{id}[,vhostforce=on|off][,queues=n]
> > > > > > >
> > > > > > >  Establish a vhost-user netdev, backed by a chardev @var{id}.
> > > > > > > The chardev should  be a unix domain socket backed one. The
> > > > > > > vhost-user uses a specifically defined  protocol to pass vhost
> > > > > > > ioctl replacement messages to an application on the other  end
> > > > > > > of the socket. On non-MSIX guests, the feature can be forced with -
> > @var{vhostforce}.
> > > > > > > +@var{vhostforce}. Use 'queues=@var{n}' to specify the number
> > > > > > > +of queues to be created for multiqueue vhost-user.
> > > > > > >
> > > > > > >  Example:
> > > > > > >  @example
> > > > > > > --
> > > > > > > 1.8.4.2
> > > > > > >

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-08-13  9:18     ` Michael S. Tsirkin
                         ` (2 preceding siblings ...)
  2015-09-01  9:13       ` [Qemu-devel] " Yuanhan Liu
@ 2015-09-07 11:07       ` Marcel Apfelbaum
  2015-09-07 12:26         ` Michael S. Tsirkin
  3 siblings, 1 reply; 44+ messages in thread
From: Marcel Apfelbaum @ 2015-09-07 11:07 UTC (permalink / raw)
  To: Michael S. Tsirkin, Ouyang Changchun
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke, thomas.long

On 08/13/2015 12:18 PM, Michael S. Tsirkin wrote:
> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
>> Based on patch by Nikolay Nikolaev:
>> Vhost-user will implement the multi queue support in a similar way
>> to what vhost already has - a separate thread for each queue.
>> To enable the multi queue functionality - a new command line parameter
>> "queues" is introduced for the vhost-user netdev.
>>
>> The RESET_OWNER change is based on commit:
>>     294ce717e0f212ed0763307f3eab72b4a1bdf4d0
>> If it is reverted, the patch need update for it accordingly.
>>
>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>> ---
>> Changes since v5:
>>   - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
>>
>> Changes since v4:
>>   - remove the unnecessary trailing '\n'
>>
>> Changes since v3:
>>   - fix one typo and wrap one long line
>>
>> Changes since v2:
>>   - fix vq index issue for set_vring_call
>>     When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
>>     thus it could be a random value. The random value leads to crash in vhost after passing down
>>     to vhost, as vhost use this random value to index an array index.
>>   - fix the typo in the doc and description
>>   - address vq index for reset_owner
>>
>> Changes since v1:
>>   - use s->nc.info_str when bringing up/down the backend
>>
>>   docs/specs/vhost-user.txt |  7 ++++++-
>>   hw/net/vhost_net.c        |  3 ++-
>>   hw/virtio/vhost-user.c    | 11 ++++++++++-
>>   net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>>   qapi-schema.json          |  6 +++++-
>>   qemu-options.hx           |  5 +++--
>>   6 files changed, 50 insertions(+), 19 deletions(-)
>>

[...]

>
>
> There are two problems here:
>
> 1. we don't really know that the backend
>     is able to support the requested number of queues.
>     If not, everything will fail, silently.
>     A new message to query the # of queues could help, though
>     I'm not sure what can be done on failure. Fail connection?
>
> 2. each message (e.g. set memory table) is sent multiple times,
>     on the same socket.

Hi,

Actually each queue has its own vhost_dev device which in turn has his own
memory mappings. Because of this VHOST_SET_MEM_TABLE should be sent for each queue.

Should we change it to VHOST_SET_VRING_MEM_TABLE? Or maybe I got this wrong...

Thanks,
Marcel




>
>
>

[...]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-07 11:07       ` Marcel Apfelbaum
@ 2015-09-07 12:26         ` Michael S. Tsirkin
  2015-09-07 13:08           ` Marcel Apfelbaum
  0 siblings, 1 reply; 44+ messages in thread
From: Michael S. Tsirkin @ 2015-09-07 12:26 UTC (permalink / raw)
  To: marcel
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On Mon, Sep 07, 2015 at 02:07:38PM +0300, Marcel Apfelbaum wrote:
> On 08/13/2015 12:18 PM, Michael S. Tsirkin wrote:
> >On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
> >>Based on patch by Nikolay Nikolaev:
> >>Vhost-user will implement the multi queue support in a similar way
> >>to what vhost already has - a separate thread for each queue.
> >>To enable the multi queue functionality - a new command line parameter
> >>"queues" is introduced for the vhost-user netdev.
> >>
> >>The RESET_OWNER change is based on commit:
> >>    294ce717e0f212ed0763307f3eab72b4a1bdf4d0
> >>If it is reverted, the patch need update for it accordingly.
> >>
> >>Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
> >>Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
> >>---
> >>Changes since v5:
> >>  - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
> >>
> >>Changes since v4:
> >>  - remove the unnecessary trailing '\n'
> >>
> >>Changes since v3:
> >>  - fix one typo and wrap one long line
> >>
> >>Changes since v2:
> >>  - fix vq index issue for set_vring_call
> >>    When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
> >>    thus it could be a random value. The random value leads to crash in vhost after passing down
> >>    to vhost, as vhost use this random value to index an array index.
> >>  - fix the typo in the doc and description
> >>  - address vq index for reset_owner
> >>
> >>Changes since v1:
> >>  - use s->nc.info_str when bringing up/down the backend
> >>
> >>  docs/specs/vhost-user.txt |  7 ++++++-
> >>  hw/net/vhost_net.c        |  3 ++-
> >>  hw/virtio/vhost-user.c    | 11 ++++++++++-
> >>  net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
> >>  qapi-schema.json          |  6 +++++-
> >>  qemu-options.hx           |  5 +++--
> >>  6 files changed, 50 insertions(+), 19 deletions(-)
> >>
> 
> [...]
> 
> >
> >
> >There are two problems here:
> >
> >1. we don't really know that the backend
> >    is able to support the requested number of queues.
> >    If not, everything will fail, silently.
> >    A new message to query the # of queues could help, though
> >    I'm not sure what can be done on failure. Fail connection?
> >
> >2. each message (e.g. set memory table) is sent multiple times,
> >    on the same socket.
> 
> Hi,
> 
> Actually each queue has its own vhost_dev device which in turn has his own
> memory mappings. Because of this VHOST_SET_MEM_TABLE should be sent for each queue.
> 
> Should we change it to VHOST_SET_VRING_MEM_TABLE? Or maybe I got this wrong...
> 
> Thanks,
> Marcel
> 

You got it wrong, the table is the same for all rings.

> 
> 
> >
> >
> >
> 
> [...]

^ permalink raw reply	[flat|nested] 44+ messages in thread

* Re: [Qemu-devel] [PATCH v6 1/2] vhost-user: add multi queue support
  2015-09-07 12:26         ` Michael S. Tsirkin
@ 2015-09-07 13:08           ` Marcel Apfelbaum
  0 siblings, 0 replies; 44+ messages in thread
From: Marcel Apfelbaum @ 2015-09-07 13:08 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: snabb-devel, thibaut.collet, qemu-devel, n.nikolaev, luke,
	thomas.long, Ouyang Changchun

On 09/07/2015 03:26 PM, Michael S. Tsirkin wrote:
> On Mon, Sep 07, 2015 at 02:07:38PM +0300, Marcel Apfelbaum wrote:
>> On 08/13/2015 12:18 PM, Michael S. Tsirkin wrote:
>>> On Wed, Aug 12, 2015 at 02:25:41PM +0800, Ouyang Changchun wrote:
>>>> Based on patch by Nikolay Nikolaev:
>>>> Vhost-user will implement the multi queue support in a similar way
>>>> to what vhost already has - a separate thread for each queue.
>>>> To enable the multi queue functionality - a new command line parameter
>>>> "queues" is introduced for the vhost-user netdev.
>>>>
>>>> The RESET_OWNER change is based on commit:
>>>>     294ce717e0f212ed0763307f3eab72b4a1bdf4d0
>>>> If it is reverted, the patch need update for it accordingly.
>>>>
>>>> Signed-off-by: Nikolay Nikolaev <n.nikolaev@virtualopensystems.com>
>>>> Signed-off-by: Changchun Ouyang <changchun.ouyang@intel.com>
>>>> ---
>>>> Changes since v5:
>>>>   - fix the message descption for VHOST_RESET_OWNER in vhost-user txt
>>>>
>>>> Changes since v4:
>>>>   - remove the unnecessary trailing '\n'
>>>>
>>>> Changes since v3:
>>>>   - fix one typo and wrap one long line
>>>>
>>>> Changes since v2:
>>>>   - fix vq index issue for set_vring_call
>>>>     When it is the case of VHOST_SET_VRING_CALL, The vq_index is not initialized before it is used,
>>>>     thus it could be a random value. The random value leads to crash in vhost after passing down
>>>>     to vhost, as vhost use this random value to index an array index.
>>>>   - fix the typo in the doc and description
>>>>   - address vq index for reset_owner
>>>>
>>>> Changes since v1:
>>>>   - use s->nc.info_str when bringing up/down the backend
>>>>
>>>>   docs/specs/vhost-user.txt |  7 ++++++-
>>>>   hw/net/vhost_net.c        |  3 ++-
>>>>   hw/virtio/vhost-user.c    | 11 ++++++++++-
>>>>   net/vhost-user.c          | 37 ++++++++++++++++++++++++-------------
>>>>   qapi-schema.json          |  6 +++++-
>>>>   qemu-options.hx           |  5 +++--
>>>>   6 files changed, 50 insertions(+), 19 deletions(-)
>>>>
>>
>> [...]
>>
>>>
>>>
>>> There are two problems here:
>>>
>>> 1. we don't really know that the backend
>>>     is able to support the requested number of queues.
>>>     If not, everything will fail, silently.
>>>     A new message to query the # of queues could help, though
>>>     I'm not sure what can be done on failure. Fail connection?
>>>
>>> 2. each message (e.g. set memory table) is sent multiple times,
>>>     on the same socket.
>>
>> Hi,
>>
>> Actually each queue has its own vhost_dev device which in turn has his own
>> memory mappings. Because of this VHOST_SET_MEM_TABLE should be sent for each queue.
>>
>> Should we change it to VHOST_SET_VRING_MEM_TABLE? Or maybe I got this wrong...
>>
>> Thanks,
>> Marcel
>>
>
> You got it wrong, the table is the same for all rings.

OK, thanks. So the backend, in this case DPDK, maps it different per each queue.
Here is an example for 2 queues:

  VHOST_CONFIG: read message VHOST_USER_SET_MEM_TABLE
  VHOST_CONFIG: mapped region 0 fd:165 to 0x2aac40000000 sz:0xa0000 off:0x0
  VHOST_CONFIG: mapped region 1 fd:166 to 0x2aac80000000 sz:0x80000000 off:0xc0000
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_NUM
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_BASE
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_KICK
  VHOST_CONFIG: vring kick idx:0 file:167 VHOST_CONFIG: virtio isn't ready for processing.
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_NUM
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_BASE
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_KICK
  VHOST_CONFIG: vring kick idx:1 file:168
  VHOST_CONFIG: virtio isn't ready for processing.
  VHOST_CONFIG: read message VHOST_USER_SET_FEATURES
  VHOST_CONFIG: read message VHOST_USER_SET_MEM_TABLE
  VHOST_CONFIG: mapped region 0 fd:169 to 0x2aad00000000 sz:0xa0000 off:0x0
  VHOST_CONFIG: mapped region 1 fd:170 to 0x2aad40000000 sz:0x80000000 off:0xc0000
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_NUM
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_BASE
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_KICK
  VHOST_CONFIG: vring kick idx:2 file:171
  VHOST_CONFIG: virtio isn't ready for processing.
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_NUM
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_BASE
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_ADDR
  VHOST_CONFIG: read message VHOST_USER_SET_VRING_KICK
  VHOST_CONFIG: vring kick idx:3 file:172
  VHOST_CONFIG: virtio is now ready for processing.

DPDK expects this message per queue and maps it to a different address.
Trying to send it only once will leave the second queue without the mapping.

I'll try to fix this on dpdk side.

Thanks,
Marcel


>
>>
>>
>>>
>>>
>>>
>>
>> [...]

^ permalink raw reply	[flat|nested] 44+ messages in thread

end of thread, other threads:[~2015-09-07 13:08 UTC | newest]

Thread overview: 44+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-28  1:23 [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Ouyang Changchun
2015-07-08 14:29 ` Michael S. Tsirkin
2015-07-08 22:00   ` Maxime Leroy
2015-07-09  1:29     ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
2015-07-09  7:31       ` Michael S. Tsirkin
2015-07-09  7:06     ` [Qemu-devel] " Michael S. Tsirkin
2015-07-09 12:00       ` Martin Kletzander
2015-07-09 12:24         ` Maxime Leroy
2015-07-09 12:33           ` Martin Kletzander
2015-07-09 12:54           ` Michael S. Tsirkin
2015-08-12  6:25 ` [Qemu-devel] [PATCH v6 0/2] vhost-user " Ouyang Changchun
2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 1/2] vhost-user: add " Ouyang Changchun
2015-08-13  9:18     ` Michael S. Tsirkin
2015-08-13 10:24       ` Maxime Leroy
2015-08-13 10:55         ` Michael S. Tsirkin
2015-08-25  3:25       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
2015-08-27 13:05         ` Michael S. Tsirkin
2015-08-28  1:53           ` Ouyang, Changchun
2015-08-30  6:16             ` Michael S. Tsirkin
2015-08-31  8:29               ` Ouyang, Changchun
2015-08-31 11:30                 ` Michael S. Tsirkin
2015-08-31 15:04                   ` Eric Blake
2015-09-01  9:20                   ` Yuanhan Liu
2015-09-01  9:41                     ` Michael S. Tsirkin
2015-09-01 12:16                       ` Yuanhan Liu
2015-09-01  9:13       ` [Qemu-devel] " Yuanhan Liu
2015-09-01 10:07         ` Michael S. Tsirkin
2015-09-01 12:15           ` Yuanhan Liu
2015-09-01 14:10             ` Michael S. Tsirkin
2015-09-02  5:45               ` Ouyang, Changchun
2015-09-02 12:10                 ` Michael S. Tsirkin
2015-09-07 11:07       ` Marcel Apfelbaum
2015-09-07 12:26         ` Michael S. Tsirkin
2015-09-07 13:08           ` Marcel Apfelbaum
2015-08-12  6:25   ` [Qemu-devel] [PATCH v6 2/2] vhost-user: new protocol feature for multi queue Ouyang Changchun
2015-08-13  9:22     ` Michael S. Tsirkin
2015-08-24  1:50       ` [Qemu-devel] [snabb-devel] " Ouyang, Changchun
2015-09-01  9:16       ` [Qemu-devel] " Yuanhan Liu
2015-09-01 10:09         ` Michael S. Tsirkin
2015-09-01 11:42           ` Yuanhan Liu
2015-08-30 15:28 ` [Qemu-devel] [PATCH v5] vhost-user: add multi queue support Marcel Apfelbaum
2015-08-31  5:28   ` Ouyang, Changchun
2015-08-31  5:42     ` Xu, Qian Q
2015-08-31  8:55       ` Marcel Apfelbaum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.