All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/17] vhost: generic vhost API
@ 2017-03-03  9:51 Yuanhan Liu
  2017-03-03  9:51 ` [PATCH 01/17] vhost: introduce driver features related APIs Yuanhan Liu
                   ` (17 more replies)
  0 siblings, 18 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

This is a first attempt to make DPDK vhost library be generic enough,
so that user could built its own vhost-user drivers on top of it. For
example, SPDK (Storage Performance Development Kit) is trying to enable
vhost-user SCSI.

The basic idea is, let DPDK vhost be a vhost-user agent. It stores all
the info about the virtio device (i.e. vring address, negotiated features,
etc) and let the specific vhost-user driver to fetch them (by the API
provided by DPDK vhost lib). With those info being provided, the vhost-user
driver then could get/put vring entries, thus, it could exchange data
between the guest and host.

The last patch demonstrates how to use these new APIs to implement a
very simple vhost-user net driver, without any fancy features enabled.


API/ABI Changes summary
=======================

- some renames
  * "struct virtio_net_device_ops" ==> "struct vhost_device_ops"
  * "rte_virtio_net.h"  ==> "rte_vhost.h"

- driver related APIs are bond with the socket file
  * rte_vhost_driver_set_features(socket_file, features);
  * rte_vhost_driver_get_features(socket_file, features);
  * rte_vhost_driver_enable_features(socket_file, features)
  * rte_vhost_driver_disable_features(socket_file, features)
  * rte_vhost_driver_callback_register(socket_file, notify_ops);

- new APIs to fetch guest and vring info
  * rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
  * rte_vhost_get_negotiated_features(int vid);
  * rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
			      struct rte_vhost_vring *vring);

- new exported structures 
  * struct rte_vhost_vring
  * struct rte_vhost_mem_region
  * struct rte_vhost_memory


Some design choices
===================

While making this patchset, I met quite few design choices and here are
two of them, with the issue and the reason I made such choices provided.
Please let me know if you have any comments (or better ideas).

Export public structures or not
-------------------------------

I made an ABI refactor last time (v16.07): move all the structures
internally and let applications use a "vid" to reference the internal
struct. With that, I hope we could never worry about the annoying ABI
issues.

It works great (and as expected) since then, as far as we only support
virito-net, as far as we can handle all the descs inside vhost lib. It
becomes problematic when a user wants to implement a vhost-user driver
somewhere. For example, it needs do the GPA to VVA translation. Without
any structs exported, some functions like gpa_to_vva() can't be inlined.
Calling it would be costly, especially it's a function we have to invoke
for processing each vring desc.

For that reason, the guest memory regions are exported. With that, the
gpa_to_vva could be inlined.

  
Add helper functions to fetch/update descs or not
-------------------------------------------------

I intended to do it like this way: introduce one function to get @count
of descs from a specific vring and another one to update the used descs.
It's something like
    rte_vhost_vring_get_descs(vid, vring_idx, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vid, vring_idx, count, offset, descs);

With that, vhost-user driver programmer's task would be easier, as he/she
doesn't have to parse the descs any more (such as to handle indirect desc).

But judging that virtio 1.1 is just emerged and it proposes a completely
ring layout, and most importantly, the vring desc structure is also changed,
I'd like to hold to introduce such two functions. Otherwise, it's very
likely the two will be invalid when virtio 1.1 is out. Though I think it
may could be addressed with a care design, something like making the IOV
generic enough:

	struct rte_vhost_iov {
		uint64_t	gpa;
		uint64_t	vva;
		uint64_t	len;
	};

Instead, I go with the other way: introduce few APIs to export all the vring
infos (vring size, vring addr, callfd, etc), and let the vhost-user driver
read and update the descs. Those info could be passed to vhost-user driver
by introducing one API for each, but for saving few APIs and reducing few
calls for the programmer, I packed few key fields into a new structure, so
that it can be fetched with one call:
        struct rte_vhost_vring {
                struct vring_desc       *desc;
                struct vring_avail      *avail;
                struct vring_used       *used;
                uint64_t                log_guest_addr;
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

When virtio 1.1 comes out, likely a simple change like following would
just work:
        struct rte_vhost_vring {
		union {
			struct {
                		struct vring_desc       *desc;
                		struct vring_avail      *avail;
                		struct vring_used       *used;
                		uint64_t                log_guest_addr;
			};
			struct desc	*desc_1_1;	/* vring addr for virtio 1.1 */
		};
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

AFAIK, it's not an ABI breakage. Even if it does, we could introduce a new
API to get the virtio 1.1 ring address.

Those fields are the minimum set I got for a specific vring, with the mind
it would bring the minimum chance to break ABI for future extension. If we
need more info, we could introduce a new API.

OTOH, for getting the best performance, the two functions also have to be
inlined ("vid + vring_idx" combo is replaced with "vring"):
    rte_vhost_vring_get_descs(vring, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vring, count, offset, descs);

That said, one way or another, we have to export rte_vhost_vring struct.
For this reason, I didn't rush into introducing the two APIs.


TODOs
=====

This series still got few small items to finish, and they are:
- update release note
- fill API comments
- set protocol features


	--yliu

---
Yuanhan Liu (17):
  vhost: introduce driver features related APIs
  net/vhost: remove feature related APIs
  vhost: use new APIs to handle features
  vhost: make notify ops per vhost driver
  vhost: export guest memory regions
  vhost: introduce API to fetch negotiated features
  vhost: export vhost vring info
  vhost: export API to translate gpa to vva
  vhost: turn queue pair to vring
  vhost: export the number of vrings
  vhost: move the device ready check at proper place
  vhost: drop the Rx and Tx queue macro
  vhost: do not include net specific headers
  vhost: rename device ops struct
  vhost: rename virtio-net to vhost
  vhost: rename header file
  examples/vhost: demonstrate the new generic vhost APIs

 doc/guides/rel_notes/deprecation.rst        |   9 -
 drivers/net/vhost/rte_eth_vhost.c           |  51 ++--
 drivers/net/vhost/rte_eth_vhost.h           |  32 +--
 drivers/net/vhost/rte_pmd_vhost_version.map |   3 -
 examples/tep_termination/main.c             |  11 +-
 examples/tep_termination/main.h             |   2 +
 examples/tep_termination/vxlan_setup.c      |   2 +-
 examples/vhost/Makefile                     |   2 +-
 examples/vhost/main.c                       |  88 ++++--
 examples/vhost/main.h                       |  33 ++-
 examples/vhost/virtio_net.c                 | 405 ++++++++++++++++++++++++++++
 lib/librte_vhost/Makefile                   |   4 +-
 lib/librte_vhost/rte_vhost.h                | 259 ++++++++++++++++++
 lib/librte_vhost/rte_vhost_version.map      |  18 +-
 lib/librte_vhost/rte_virtio_net.h           | 193 -------------
 lib/librte_vhost/socket.c                   | 143 ++++++++++
 lib/librte_vhost/vhost.c                    | 209 +++++++-------
 lib/librte_vhost/vhost.h                    |  82 +++---
 lib/librte_vhost/vhost_user.c               |  91 +++----
 lib/librte_vhost/vhost_user.h               |   2 +-
 lib/librte_vhost/virtio_net.c               |  35 +--
 21 files changed, 1140 insertions(+), 534 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

-- 
1.9.0

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

* [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14  9:46   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 02/17] net/vhost: remove feature " Yuanhan Liu
                   ` (16 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Introduce few APIs to set/get/enable/disable driver features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map | 10 ++++
 lib/librte_vhost/rte_virtio_net.h      |  9 ++++
 lib/librte_vhost/socket.c              | 90 ++++++++++++++++++++++++++++++++++
 3 files changed, 109 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 5ceaa8a..d4f2f69 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -30,3 +30,13 @@ DPDK_16.07 {
 	rte_vhost_get_queue_num;
 
 } DPDK_2.1;
+
+DPDK_17.05 {
+	global:
+
+	rte_vhost_driver_disable_features;
+	rte_vhost_driver_enable_features;
+	rte_vhost_driver_get_features;
+	rte_vhost_driver_set_features;
+
+} DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 926039c..6e166a6 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -94,6 +94,15 @@ struct virtio_net_device_ops {
 /* Unregister vhost driver. This is only meaningful to vhost user. */
 int rte_vhost_driver_unregister(const char *path);
 
+/**
+ * Set feature bits the vhost driver supports.
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+uint64_t rte_vhost_driver_get_features(const char *path);
+
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
 /* Start vhost driver session blocking loop. */
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index aaa9c27..76eb426 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -63,6 +63,16 @@ struct vhost_user_socket {
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
+
+	/*
+	 * The "supported_features" indicates the feature bits the
+	 * vhost driver supports. The "features" indicates the feature
+	 * bits after the rte_vhost_driver_features_disable/enable().
+	 * It is also the final feature bits used for vhost-user
+	 * features negotiation.
+	 */
+	uint64_t supported_features;
+	uint64_t features;
 };
 
 struct vhost_user_connection {
@@ -475,6 +485,86 @@ struct vhost_user_reconnect_list {
 	return 0;
 }
 
+static struct vhost_user_socket *
+find_vhost_user_socket(const char *path)
+{
+	int i;
+
+	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
+		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
+
+		if (!strcmp(vsocket->path, path))
+			return vsocket;
+	}
+
+	return NULL;
+}
+
+int
+rte_vhost_driver_disable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->features &= ~features;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_enable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		if ((vsocket->supported_features & features) != features) {
+			/*
+			 * trying to enable features the driver doesn't
+			 * support.
+			 */
+			pthread_mutex_unlock(&vhost_user.mutex);
+			return -1;
+		}
+		vsocket->features |= features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_set_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		vsocket->supported_features = features;
+		vsocket->features = features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+uint64_t
+rte_vhost_driver_get_features(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->features : (uint64_t)-1;
+}
+
 /*
  * Register a new vhost-user socket; here we could act as server
  * (the default case), or client (when RTE_VHOST_USER_CLIENT) flag
-- 
1.9.0

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

* [PATCH 02/17] net/vhost: remove feature related APIs
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
  2017-03-03  9:51 ` [PATCH 01/17] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 10:15   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 03/17] vhost: use new APIs to handle features Yuanhan Liu
                   ` (15 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

vdev options is better for disabling/enabling some features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/vhost/rte_eth_vhost.c           | 25 ------------------------
 drivers/net/vhost/rte_eth_vhost.h           | 30 -----------------------------
 drivers/net/vhost/rte_pmd_vhost_version.map |  3 ---
 3 files changed, 58 deletions(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 62ccb74..0ebaa4a 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -963,31 +963,6 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-/**
- * Disable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_disable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_disable(feature_mask);
-}
-
-/**
- * Enable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_enable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_enable(feature_mask);
-}
-
-/* Returns currently supported vhost features */
-uint64_t
-rte_eth_vhost_feature_get(void)
-{
-	return rte_vhost_feature_get();
-}
-
 static const struct eth_dev_ops ops = {
 	.dev_start = eth_dev_start,
 	.dev_stop = eth_dev_stop,
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index 7c98b1a..ea4bce4 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -43,36 +43,6 @@
 
 #include <rte_virtio_net.h>
 
-/**
- * Disable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- * Enable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_enable(uint64_t feature_mask);
-
-/**
- * Returns currently supported vhost features.
- *
- * @return
- *  Vhost features defined in "linux/virtio_net.h".
- */
-uint64_t rte_eth_vhost_feature_get(void);
-
 /*
  * Event description.
  */
diff --git a/drivers/net/vhost/rte_pmd_vhost_version.map b/drivers/net/vhost/rte_pmd_vhost_version.map
index 3d44083..695db85 100644
--- a/drivers/net/vhost/rte_pmd_vhost_version.map
+++ b/drivers/net/vhost/rte_pmd_vhost_version.map
@@ -1,9 +1,6 @@
 DPDK_16.04 {
 	global:
 
-	rte_eth_vhost_feature_disable;
-	rte_eth_vhost_feature_enable;
-	rte_eth_vhost_feature_get;
 	rte_eth_vhost_get_queue_event;
 
 	local: *;
-- 
1.9.0

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

* [PATCH 03/17] vhost: use new APIs to handle features
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
  2017-03-03  9:51 ` [PATCH 01/17] vhost: introduce driver features related APIs Yuanhan Liu
  2017-03-03  9:51 ` [PATCH 02/17] net/vhost: remove feature " Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 10:43   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 04/17] vhost: make notify ops per vhost driver Yuanhan Liu
                   ` (14 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/tep_termination/main.c        |  4 +++-
 examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
 lib/librte_vhost/rte_vhost_version.map |  3 ---
 lib/librte_vhost/rte_virtio_net.h      | 13 ----------
 lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
 lib/librte_vhost/vhost.c               | 41 --------------------------------
 lib/librte_vhost/vhost.h               | 20 ++++++++++++++++
 lib/librte_vhost/vhost_user.c          |  8 +++----
 8 files changed, 76 insertions(+), 79 deletions(-)

diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index bd1dc96..8c45128 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1250,12 +1250,14 @@ static inline void __attribute__((always_inline))
 		rte_eal_remote_launch(switch_worker,
 			mbuf_pool, lcore_id);
 	}
-	rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
 	ret = rte_vhost_driver_register((char *)&dev_basename, 0);
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "failed to register vhost driver.\n");
 
+	rte_vhost_driver_disable_features(dev_basename,
+		1ULL << VIRTIO_NET_F_MRG_RXBUF);
+
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
 
 	rte_vhost_driver_session_start();
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4789947..972a6a8 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -328,16 +328,6 @@ struct mbuf_table {
 
 	if (port >= rte_eth_dev_count()) return -1;
 
-	if (enable_tx_csum == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM);
-
-	if (enable_tso == 0) {
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
-	}
-
 	rx_rings = (uint16_t)dev_info.max_rx_queues;
 	/* Configure ethernet device. */
 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
@@ -531,7 +521,6 @@ struct mbuf_table {
 			vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode =
 				ETH_VMDQ_ACCEPT_BROADCAST |
 				ETH_VMDQ_ACCEPT_MULTICAST;
-			rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX);
 
 			break;
 
@@ -1509,9 +1498,6 @@ static inline void __attribute__((always_inline))
 	RTE_LCORE_FOREACH_SLAVE(lcore_id)
 		rte_eal_remote_launch(switch_worker, NULL, lcore_id);
 
-	if (mergeable == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
-
 	if (client_mode)
 		flags |= RTE_VHOST_USER_CLIENT;
 
@@ -1520,13 +1506,38 @@ static inline void __attribute__((always_inline))
 
 	/* Register vhost user driver to handle vhost messages. */
 	for (i = 0; i < nb_sockets; i++) {
-		ret = rte_vhost_driver_register
-				(socket_files + i * PATH_MAX, flags);
+		char *file = socket_files + i * PATH_MAX;
+		ret = rte_vhost_driver_register(file, flags);
 		if (ret != 0) {
 			unregister_drivers(i);
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+		if (mergeable == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_MRG_RXBUF);
+		}
+
+		if (enable_tx_csum == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_CSUM);
+		}
+
+		if (enable_tso == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO6);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO6);
+		}
+
+		if (promiscuous) {
+			rte_vhost_driver_enable_features(file,
+				1ULL << VIRTIO_NET_F_CTRL_RX);
+		}
 	}
 
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index d4f2f69..ee72d5f 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -7,9 +7,6 @@ DPDK_2.0 {
 	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
-	rte_vhost_feature_disable;
-	rte_vhost_feature_enable;
-	rte_vhost_feature_get;
 
 	local: *;
 };
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 6e166a6..51f5166 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -70,19 +70,6 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
-/**
- *  Disable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- *  Enable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_enable(uint64_t feature_mask);
-
-/* Returns currently supported vhost features */
-uint64_t rte_vhost_feature_get(void);
-
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 76eb426..9e0ec05 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -500,6 +500,21 @@ struct vhost_user_reconnect_list {
 	return NULL;
 }
 
+/*
+ * Applications know nothing about features the builtin virtio net
+ * driver (virtio_net.c) supports, thus it's not possible for them
+ * to invoke rte_vhost_driver_set_features(). To workaround it, here
+ * we set it when no such call is invoked.
+ */
+static void
+workaround_builtin_virtio_net_features(struct vhost_user_socket *vsocket)
+{
+	if (vsocket->supported_features == UINT64_MAX) {
+		vsocket->supported_features = VIRTIO_NET_SUPPORTED_FEATURES;
+		vsocket->features           = VIRTIO_NET_SUPPORTED_FEATURES;
+	}
+}
+
 int
 rte_vhost_driver_disable_features(const char *path, uint64_t features)
 {
@@ -507,8 +522,10 @@ struct vhost_user_reconnect_list {
 
 	pthread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
-	if (vsocket)
+	if (vsocket) {
+		workaround_builtin_virtio_net_features(vsocket);
 		vsocket->features &= ~features;
+	}
 	pthread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? 0 : -1;
@@ -522,6 +539,7 @@ struct vhost_user_reconnect_list {
 	pthread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
 	if (vsocket) {
+		workaround_builtin_virtio_net_features(vsocket);
 		if ((vsocket->supported_features & features) != features) {
 			/*
 			 * trying to enable features the driver doesn't
@@ -560,6 +578,8 @@ struct vhost_user_reconnect_list {
 
 	pthread_mutex_lock(&vhost_user.mutex);
 	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		workaround_builtin_virtio_net_features(vsocket);
 	pthread_mutex_unlock(&vhost_user.mutex);
 
 	return vsocket ? vsocket->features : (uint64_t)-1;
@@ -594,6 +614,7 @@ struct vhost_user_reconnect_list {
 	vsocket->path = strdup(path);
 	vsocket->connfd = -1;
 	vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
+	vsocket->supported_features = UINT64_MAX;
 
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 3c3f6a4..2790f17 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -49,27 +49,6 @@
 
 #include "vhost.h"
 
-#define VHOST_USER_F_PROTOCOL_FEATURES	30
-
-/* Features supported by this lib. */
-#define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
-				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
-				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
-				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
-				(1ULL << VIRTIO_NET_F_MQ)      | \
-				(1ULL << VIRTIO_F_VERSION_1)   | \
-				(1ULL << VHOST_F_LOG_ALL)      | \
-				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
-				(1ULL << VIRTIO_NET_F_CSUM)    | \
-				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
-				(1ULL << VIRTIO_RING_F_INDIRECT_DESC))
-
-uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
-
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
 /* device ops to add/remove device to/from data core. */
@@ -399,26 +378,6 @@ struct virtio_net *
 	return 0;
 }
 
-uint64_t rte_vhost_feature_get(void)
-{
-	return VHOST_FEATURES;
-}
-
-int rte_vhost_feature_disable(uint64_t feature_mask)
-{
-	VHOST_FEATURES = VHOST_FEATURES & ~feature_mask;
-	return 0;
-}
-
-int rte_vhost_feature_enable(uint64_t feature_mask)
-{
-	if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) {
-		VHOST_FEATURES = VHOST_FEATURES | feature_mask;
-		return 0;
-	}
-	return -1;
-}
-
 /*
  * Register ops so that we can add/remove device to data core.
  */
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index d97df1d..61e7448 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -44,6 +44,26 @@
 
 #include "rte_virtio_net.h"
 
+#define VHOST_USER_F_PROTOCOL_FEATURES	30
+
+/* Features supported by this lib. */
+#define VIRTIO_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
+				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
+				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+				(1ULL << VIRTIO_NET_F_MQ)      | \
+				(1ULL << VIRTIO_F_VERSION_1)   | \
+				(1ULL << VHOST_F_LOG_ALL)      | \
+				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
+				(1ULL << VIRTIO_NET_F_CSUM)    | \
+				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+				(1ULL << VIRTIO_RING_F_INDIRECT_DESC))
+
+
 /* Used to indicate that the device is running on a data core */
 #define VIRTIO_DEV_RUNNING 1
 
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 8433a54..f7227bf 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -143,9 +143,9 @@
  * The features that we support are requested.
  */
 static uint64_t
-vhost_user_get_features(void)
+vhost_user_get_features(struct virtio_net *dev)
 {
-	return VHOST_FEATURES;
+	return rte_vhost_driver_get_features(dev->ifname);
 }
 
 /*
@@ -154,7 +154,7 @@
 static int
 vhost_user_set_features(struct virtio_net *dev, uint64_t features)
 {
-	if (features & ~VHOST_FEATURES)
+	if (features & ~rte_vhost_driver_get_features(dev->ifname))
 		return -1;
 
 	dev->features = features;
@@ -980,7 +980,7 @@
 
 	switch (msg.request) {
 	case VHOST_USER_GET_FEATURES:
-		msg.payload.u64 = vhost_user_get_features();
+		msg.payload.u64 = vhost_user_get_features(dev);
 		msg.size = sizeof(msg.payload.u64);
 		send_vhost_message(fd, &msg);
 		break;
-- 
1.9.0

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

* [PATCH 04/17] vhost: make notify ops per vhost driver
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (2 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 03/17] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 10:55   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 05/17] vhost: export guest memory regions Yuanhan Liu
                   ` (13 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Assume there is an application both support vhost-user net and
vhost-user scsi, the callback should be different. Making notify
ops per vhost driver allow application define different set of
callbacks for different driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/vhost/rte_eth_vhost.c | 20 +++++++++++---------
 examples/tep_termination/main.c   |  3 ++-
 examples/vhost/main.c             |  5 +++--
 lib/librte_vhost/rte_virtio_net.h |  3 ++-
 lib/librte_vhost/socket.c         | 32 ++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c          | 16 +---------------
 lib/librte_vhost/vhost.h          |  5 ++++-
 lib/librte_vhost/vhost_user.c     | 15 +++++++++------
 8 files changed, 64 insertions(+), 35 deletions(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 0ebaa4a..816a9a0 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -667,6 +667,12 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
+static struct virtio_net_device_ops vhost_ops = {
+	.new_device          = new_device,
+	.destroy_device      = destroy_device,
+	.vring_state_changed = vring_state_changed,
+};
+
 int
 rte_eth_vhost_get_queue_event(uint8_t port_id,
 		struct rte_eth_vhost_queue_event *event)
@@ -736,15 +742,6 @@ struct vhost_xstats_name_off {
 static void *
 vhost_driver_session(void *param __rte_unused)
 {
-	static struct virtio_net_device_ops vhost_ops;
-
-	/* set vhost arguments */
-	vhost_ops.new_device = new_device;
-	vhost_ops.destroy_device = destroy_device;
-	vhost_ops.vring_state_changed = vring_state_changed;
-	if (rte_vhost_driver_callback_register(&vhost_ops) < 0)
-		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
-
 	/* start event handling */
 	rte_vhost_driver_session_start();
 
@@ -1077,6 +1074,11 @@ struct vhost_xstats_name_off {
 	if (rte_vhost_driver_register(iface_name, flags))
 		goto error;
 
+	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
+		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
+		goto error;
+	}
+
 	/* We need only one message handling thread */
 	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
 		if (vhost_driver_session_start())
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 8c45128..03c0fbe 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1258,7 +1258,8 @@ static inline void __attribute__((always_inline))
 	rte_vhost_driver_disable_features(dev_basename,
 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+	rte_vhost_driver_callback_register(dev_basename,
+		&virtio_net_device_ops);
 
 	rte_vhost_driver_session_start();
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 972a6a8..867efc6 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1538,9 +1538,10 @@ static inline void __attribute__((always_inline))
 			rte_vhost_driver_enable_features(file,
 				1ULL << VIRTIO_NET_F_CTRL_RX);
 		}
-	}
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+		rte_vhost_driver_callback_register(file,
+			&virtio_net_device_ops);
+	}
 
 	rte_vhost_driver_session_start();
 	return 0;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 51f5166..3bfd0b7 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -91,7 +91,8 @@ struct virtio_net_device_ops {
 int rte_vhost_driver_disable_features(const char *path, uint64_t features);
 
 /* Register callbacks. */
-int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
+int rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 9e0ec05..550af64 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -73,6 +73,8 @@ struct vhost_user_socket {
 	 */
 	uint64_t supported_features;
 	uint64_t features;
+
+	struct virtio_net_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -718,6 +720,36 @@ struct vhost_user_reconnect_list {
 	return -1;
 }
 
+/*
+ * Register ops so that we can add/remove device to data core.
+ */
+int
+rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->notify_ops = ops;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+struct virtio_net_device_ops const *
+vhost_driver_callback_get(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket->notify_ops;
+}
+
 int
 rte_vhost_driver_session_start(void)
 {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 2790f17..0088f87 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -51,9 +51,6 @@
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* device ops to add/remove device to/from data core. */
-struct virtio_net_device_ops const *notify_ops;
-
 struct virtio_net *
 get_device(int vid)
 {
@@ -253,7 +250,7 @@ struct virtio_net *
 
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(vid);
+		dev->notify_ops->destroy_device(vid);
 	}
 
 	cleanup_device(dev, 1);
@@ -377,14 +374,3 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
-
-/*
- * Register ops so that we can add/remove device to data core.
- */
-int
-rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
-{
-	notify_ops = ops;
-
-	return 0;
-}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 61e7448..bc03e09 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -177,6 +177,8 @@ struct virtio_net {
 	uint64_t		log_addr;
 	struct ether_addr	mac;
 
+	struct virtio_net_device_ops const *notify_ops;
+
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
 	struct guest_page       *guest_pages;
@@ -280,7 +282,6 @@ static inline phys_addr_t __attribute__((always_inline))
 	return 0;
 }
 
-struct virtio_net_device_ops const *notify_ops;
 struct virtio_net *get_device(int vid);
 
 int vhost_new_device(void);
@@ -293,6 +294,8 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
+struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+
 /*
  * Backend-specific cleanup.
  *
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index f7227bf..c101fbc 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -131,7 +131,7 @@
 {
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	cleanup_device(dev, 0);
@@ -499,7 +499,7 @@
 	/* Remove from the data plane. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	if (dev->mem) {
@@ -680,7 +680,7 @@
 				"dequeue zero copy is enabled\n");
 		}
 
-		if (notify_ops->new_device(dev->vid) == 0)
+		if (dev->notify_ops->new_device(dev->vid) == 0)
 			dev->flags |= VIRTIO_DEV_RUNNING;
 	}
 }
@@ -713,7 +713,7 @@
 	/* We have to stop the queue (virtio) if it is running. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	/* Here we are safe to get the last used index */
@@ -753,8 +753,8 @@
 		"set queue enable: %d to qp idx: %d\n",
 		enable, state->index);
 
-	if (notify_ops->vring_state_changed)
-		notify_ops->vring_state_changed(dev->vid, state->index, enable);
+	if (dev->notify_ops->vring_state_changed)
+		dev->notify_ops->vring_state_changed(dev->vid, state->index, enable);
 
 	dev->virtqueue[state->index]->enabled = enable;
 
@@ -952,6 +952,9 @@
 	if (dev == NULL)
 		return -1;
 
+	if (!dev->notify_ops)
+		dev->notify_ops = vhost_driver_callback_get(dev->ifname);
+
 	ret = read_vhost_message(fd, &msg);
 	if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
 		if (ret < 0)
-- 
1.9.0

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

* [PATCH 05/17] vhost: export guest memory regions
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (3 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 04/17] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 11:00   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 06/17] vhost: introduce API to fetch negotiated features Yuanhan Liu
                   ` (12 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Some vhost-user driver may need this info to setup its own page tables
for GPA (guest physical addr) to HPA (host physical addr) translation.
SPDK (Storage Performance Development Kit) is one example.

Besides, by exporting this memory info, we could also export the
gpa_to_vva() as an inline function, which helps for performance.
Otherwise, it has to be referenced indirectly by a "vid".

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 24 ++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 23 +++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 28 ++--------------------------
 lib/librte_vhost/vhost_user.c          | 12 ++++++------
 5 files changed, 56 insertions(+), 32 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index ee72d5f..b890da6 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -35,5 +35,6 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_get_vhost_memory;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 3bfd0b7..eddf0f4 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -59,6 +59,28 @@
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
 /**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+/**
  * Device and vring operations.
  */
 struct virtio_net_device_ops {
@@ -187,4 +209,6 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
 uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
 
+int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 0088f87..eee229a 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -340,6 +340,29 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem)
+{
+	struct virtio_net *dev;
+	struct rte_vhost_memory *m;
+	size_t size;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
+	m = malloc(size);
+	if (!m)
+		return -1;
+
+	m->nregions = dev->mem->nregions;
+	memcpy(m->regions, dev->mem->regions, size);
+	*mem = m;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index bc03e09..ed7b2c9 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -159,7 +159,7 @@ struct guest_page {
  */
 struct virtio_net {
 	/* Frontend (QEMU) memory and memory region information */
-	struct virtio_memory	*mem;
+	struct rte_vhost_memory	*mem;
 	uint64_t		features;
 	uint64_t		protocol_features;
 	int			vid;
@@ -184,30 +184,6 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct virtio_memory_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct virtio_memory {
-	uint32_t nregions;
-	struct virtio_memory_region regions[0];
-};
-
-
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
@@ -247,7 +223,7 @@ struct virtio_memory {
 static inline uint64_t __attribute__((always_inline))
 gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	for (i = 0; i < dev->mem->nregions; i++) {
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index c101fbc..05dbc87 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -88,7 +88,7 @@
 free_mem_region(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 
 	if (!dev || !dev->mem)
 		return;
@@ -300,7 +300,7 @@
 static uint64_t
 qva_to_vva(struct virtio_net *dev, uint64_t qva)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	/* Find the region where the address lives. */
@@ -428,7 +428,7 @@
 }
 
 static void
-add_guest_pages(struct virtio_net *dev, struct virtio_memory_region *reg,
+add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 		uint64_t page_size)
 {
 	uint64_t reg_size = reg->size;
@@ -488,7 +488,7 @@
 vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
 	struct VhostUserMemory memory = pmsg->payload.memory;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	void *mmap_addr;
 	uint64_t mmap_size;
 	uint64_t mmap_offset;
@@ -515,8 +515,8 @@
 						sizeof(struct guest_page));
 	}
 
-	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct virtio_memory) +
-		sizeof(struct virtio_memory_region) * memory.nregions, 0);
+	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct rte_vhost_memory) +
+		sizeof(struct rte_vhost_mem_region) * memory.nregions, 0);
 	if (dev->mem == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"(%d) failed to allocate memory for dev->mem\n",
-- 
1.9.0

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

* [PATCH 06/17] vhost: introduce API to fetch negotiated features
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (4 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 05/17] vhost: export guest memory regions Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 11:02   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 07/17] vhost: export vhost vring info Yuanhan Liu
                   ` (11 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      |  1 +
 lib/librte_vhost/vhost.c               | 12 ++++++++++++
 3 files changed, 14 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index b890da6..85a2796 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -35,6 +35,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index eddf0f4..e7b1599 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -210,5 +210,6 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
 
 int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
+uint64_t rte_vhost_get_negotiated_features(int vid);
 
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index eee229a..8046aef 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -340,6 +340,18 @@ struct virtio_net *
 	return 0;
 }
 
+uint64_t
+rte_vhost_get_negotiated_features(int vid)
+{
+	struct virtio_net *dev;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	return dev->features;
+}
+
 int
 rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem)
 {
-- 
1.9.0

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

* [PATCH 07/17] vhost: export vhost vring info
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (5 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 06/17] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:11   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 08/17] vhost: export API to translate gpa to vva Yuanhan Liu
                   ` (10 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 13 +++++++++++++
 lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               |  2 ++
 4 files changed, 46 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 85a2796..efde936 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -37,5 +37,6 @@ DPDK_17.05 {
 	rte_vhost_driver_set_features;
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
+	rte_vhost_get_vhost_vring;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index e7b1599..80209ad 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -80,6 +80,17 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[0];
 };
 
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
 /**
  * Device and vring operations.
  */
@@ -211,5 +222,7 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 
 int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
 uint64_t rte_vhost_get_negotiated_features(int vid);
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
 
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 8046aef..b175f0e 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -375,6 +375,36 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			  struct rte_vhost_vring *vring)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	if (vring_idx > VHOST_MAX_VRING)
+		return -1;
+
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return -1;
+
+	vring->desc  = vq->desc;
+	vring->avail = vq->avail;
+	vring->used  = vq->used;
+	vring->log_guest_addr  = vq->log_guest_addr;
+
+	vring->callfd  = vq->callfd;
+	vring->kickfd  = vq->kickfd;
+	vring->size    = vq->size;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index ed7b2c9..b0ef0cc 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -138,6 +138,8 @@ struct vhost_virtqueue {
 #ifndef VIRTIO_NET_F_MQ
  #define VIRTIO_NET_F_MQ		22
 #endif
+
+#define VHOST_MAX_VRING			0x100
 #define VHOST_MAX_QUEUE_PAIRS		0x80
 
 /*
-- 
1.9.0

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

* [PATCH 08/17] vhost: export API to translate gpa to vva
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (6 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 07/17] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:24   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 09/17] vhost: turn queue pair to vring Yuanhan Liu
                   ` (9 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 21 +++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 19 -------------------
 lib/librte_vhost/virtio_net.c          | 23 +++++++++++++----------
 4 files changed, 35 insertions(+), 29 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index efde936..24f31ee 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -38,5 +38,6 @@ DPDK_17.05 {
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 80209ad..dbdf004 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -103,6 +103,27 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
+/**
+ * Convert guest physical Address to host virtual address
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index b0ef0cc..fb19742 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -221,25 +221,6 @@ struct virtio_net {
 #define MAX_VHOST_DEVICE	1024
 extern struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* Convert guest physical Address to host virtual address */
-static inline uint64_t __attribute__((always_inline))
-gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < dev->mem->nregions; i++) {
-		reg = &dev->mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
 /* Convert guest physical address to host physical address */
 static inline phys_addr_t __attribute__((always_inline))
 gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 337470d..6b9b4c3 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -199,7 +199,7 @@ static inline int __attribute__((always_inline))
 	uint16_t nr_desc = 1;
 
 	desc = &descs[desc_idx];
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	/*
 	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
 	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
@@ -239,7 +239,7 @@ static inline int __attribute__((always_inline))
 				return -1;
 
 			desc = &descs[desc->next];
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -323,7 +323,8 @@ static inline uint32_t __attribute__((always_inline))
 		int err;
 
 		if (vq->desc[desc_idx].flags & VRING_DESC_F_INDIRECT) {
-			descs = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			descs = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_idx].addr);
 			if (unlikely(!descs)) {
 				count = i;
@@ -383,7 +384,7 @@ static inline int __attribute__((always_inline))
 
 	if (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) {
 		descs = (struct vring_desc *)(uintptr_t)
-					gpa_to_vva(dev, vq->desc[idx].addr);
+			rte_vhost_gpa_to_vva(dev->mem, vq->desc[idx].addr);
 		if (unlikely(!descs))
 			return -1;
 
@@ -473,7 +474,7 @@ static inline int __attribute__((always_inline))
 	if (unlikely(m == NULL))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, buf_vec[vec_idx].buf_addr);
 	if (buf_vec[vec_idx].buf_len < dev->vhost_hlen || !desc_addr)
 		return -1;
 
@@ -495,7 +496,8 @@ static inline int __attribute__((always_inline))
 		/* done with current desc buf, get the next one */
 		if (desc_avail == 0) {
 			vec_idx++;
-			desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem,
+					buf_vec[vec_idx].buf_addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -798,7 +800,7 @@ static inline int __attribute__((always_inline))
 			(desc->flags & VRING_DESC_F_INDIRECT))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	if (unlikely(!desc_addr))
 		return -1;
 
@@ -818,7 +820,7 @@ static inline int __attribute__((always_inline))
 		if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 			return -1;
 
-		desc_addr = gpa_to_vva(dev, desc->addr);
+		desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 		if (unlikely(!desc_addr))
 			return -1;
 
@@ -882,7 +884,7 @@ static inline int __attribute__((always_inline))
 			if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 				return -1;
 
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -1113,7 +1115,8 @@ static inline bool __attribute__((always_inline))
 			rte_prefetch0(&vq->desc[desc_indexes[i + 1]]);
 
 		if (vq->desc[desc_indexes[i]].flags & VRING_DESC_F_INDIRECT) {
-			desc = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			desc = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_indexes[i]].addr);
 			if (unlikely(!desc))
 				break;
-- 
1.9.0

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

* [PATCH 09/17] vhost: turn queue pair to vring
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (7 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 08/17] vhost: export API to translate gpa to vva Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:31   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 10/17] vhost: export the number of vrings Yuanhan Liu
                   ` (8 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The queue pair is very virtio-net specific, other devices don't have
such concept. To make it generic, we should log the number of vrings
instead of the number of queue pairs.

This patch just does a simple convert, a later patch would export the
number of vrings to applications.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/vhost.c      | 74 ++++++++++++++-----------------------------
 lib/librte_vhost/vhost.h      |  4 +--
 lib/librte_vhost/vhost_user.c | 28 +++++-----------
 lib/librte_vhost/virtio_net.c | 10 +++---
 4 files changed, 38 insertions(+), 78 deletions(-)

diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index b175f0e..82fb2b7 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -84,10 +84,8 @@ struct virtio_net *
 
 	vhost_backend_cleanup(dev);
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ], destroy);
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ], destroy);
-	}
+	for (i = 0; i < dev->nr_vring; i++)
+		cleanup_vq(dev->virtqueue[i], destroy);
 }
 
 /*
@@ -97,24 +95,21 @@ struct virtio_net *
 free_device(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct vhost_virtqueue *rxq, *txq;
+	struct vhost_virtqueue *vq;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rxq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		txq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		rte_free(rxq->shadow_used_ring);
-		rte_free(txq->shadow_used_ring);
+		rte_free(vq->shadow_used_ring);
 
-		/* rxq and txq are allocated together as queue-pair */
-		rte_free(rxq);
+		rte_free(vq);
 	}
 
 	rte_free(dev);
 }
 
 static void
-init_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+init_vring_queue(struct vhost_virtqueue *vq, int vring_idx)
 {
 	memset(vq, 0, sizeof(struct vhost_virtqueue));
 
@@ -125,68 +120,45 @@ struct virtio_net *
 	vq->backend = -1;
 
 	/* always set the default vq pair to enabled */
-	if (qp_idx == 0)
+	if (vring_idx / 2 == 0)
 		vq->enabled = 1;
 
 	TAILQ_INIT(&vq->zmbuf_list);
 }
 
 static void
-init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
-static void
-reset_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+reset_vring_queue(struct vhost_virtqueue *vq, int vring_idx)
 {
 	int callfd;
 
 	callfd = vq->callfd;
-	init_vring_queue(vq, qp_idx);
+	init_vring_queue(vq, vring_idx);
 	vq->callfd = callfd;
 }
 
-static void
-reset_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
 int
-alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
+alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {
-	struct vhost_virtqueue *virtqueue = NULL;
-	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
-	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
+	struct vhost_virtqueue *vq;
 
-	virtqueue = rte_malloc(NULL,
-			       sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);
-	if (virtqueue == NULL) {
+	vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
+	if (vq == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
-			"Failed to allocate memory for virt qp:%d.\n", qp_idx);
+			"Failed to allocate memory for vring:%u.\n", vring_idx);
 		return -1;
 	}
 
-	dev->virtqueue[virt_rx_q_idx] = virtqueue;
-	dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
-
-	init_vring_queue_pair(dev, qp_idx);
+	dev->virtqueue[vring_idx] = vq;
+	init_vring_queue(vq, vring_idx);
 
-	dev->virt_qp_nb += 1;
+	dev->nr_vring += 1;
 
 	return 0;
 }
 
 /*
  * Reset some variables in device structure, while keeping few
- * others untouched, such as vid, ifname, virt_qp_nb: they
+ * others untouched, such as vid, ifname, nr_vring: they
  * should be same unless the device is removed.
  */
 void
@@ -198,8 +170,8 @@ struct virtio_net *
 	dev->protocol_features = 0;
 	dev->flags = 0;
 
-	for (i = 0; i < dev->virt_qp_nb; i++)
-		reset_vring_queue_pair(dev, i);
+	for (i = 0; i < dev->nr_vring; i++)
+		reset_vring_queue(dev->virtqueue[i], i);
 }
 
 /*
@@ -321,7 +293,7 @@ struct virtio_net *
 	if (dev == NULL)
 		return 0;
 
-	return dev->virt_qp_nb;
+	return dev->nr_vring / 2;
 }
 
 int
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index fb19742..829a45b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -169,7 +169,7 @@ struct virtio_net {
 	uint16_t		vhost_hlen;
 	/* to tell if we need broadcast rarp packet */
 	rte_atomic16_t		broadcast_rarp;
-	uint32_t		virt_qp_nb;
+	uint32_t		nr_vring;
 	int			dequeue_zero_copy;
 	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
@@ -248,7 +248,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void reset_device(struct virtio_net *dev);
 void vhost_destroy_device(int);
 
-int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
+int alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 05dbc87..fdf6f62 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -223,13 +223,6 @@
 	struct vhost_virtqueue *old_vq, *vq;
 	int ret;
 
-	/*
-	 * vq is allocated on pairs, we should try to do realloc
-	 * on first queue of one queue pair only.
-	 */
-	if (index % VIRTIO_QNUM != 0)
-		return dev;
-
 	old_dev = dev;
 	vq = old_vq = dev->virtqueue[index];
 
@@ -247,8 +240,7 @@
 	if (oldnode != newnode) {
 		RTE_LOG(INFO, VHOST_CONFIG,
 			"reallocate vq from %d to %d node\n", oldnode, newnode);
-		vq = rte_malloc_socket(NULL, sizeof(*vq) * VIRTIO_QNUM, 0,
-				       newnode);
+		vq = rte_malloc_socket(NULL, sizeof(*vq), 0, newnode);
 		if (!vq)
 			return dev;
 
@@ -280,7 +272,6 @@
 
 out:
 	dev->virtqueue[index] = vq;
-	dev->virtqueue[index + 1] = vq + 1;
 	vhost_devices[dev->vid] = dev;
 
 	return dev;
@@ -611,14 +602,13 @@
 static int
 virtio_is_ready(struct virtio_net *dev)
 {
-	struct vhost_virtqueue *rvq, *tvq;
+	struct vhost_virtqueue *vq;
 	uint32_t i;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		tvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(rvq) || !vq_is_ready(tvq)) {
+		if (!vq_is_ready(vq)) {
 			RTE_LOG(INFO, VHOST_CONFIG,
 				"virtio is not ready for processing.\n");
 			return 0;
@@ -908,7 +898,6 @@
 vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev, VhostUserMsg *msg)
 {
 	uint16_t vring_idx;
-	uint16_t qp_idx;
 
 	switch (msg->request) {
 	case VHOST_USER_SET_VRING_KICK:
@@ -928,17 +917,16 @@
 		return 0;
 	}
 
-	qp_idx = vring_idx / VIRTIO_QNUM;
-	if (qp_idx >= VHOST_MAX_QUEUE_PAIRS) {
+	if (vring_idx >= VHOST_MAX_VRING) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"invalid vring index: %u\n", vring_idx);
 		return -1;
 	}
 
-	if (dev->virtqueue[qp_idx])
+	if (dev->virtqueue[vring_idx])
 		return 0;
 
-	return alloc_vring_queue_pair(dev, qp_idx);
+	return alloc_vring_queue(dev, vring_idx);
 }
 
 int
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 6b9b4c3..8ed2b93 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -86,9 +86,9 @@ static inline void __attribute__((always_inline))
 }
 
 static bool
-is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t qp_nb)
+is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
 {
-	return (is_tx ^ (idx & 1)) == 0 && idx < qp_nb * VIRTIO_QNUM;
+	return (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;
 }
 
 static inline void __attribute__((always_inline))
@@ -283,7 +283,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint32_t i, sz;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -554,7 +554,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint16_t avail_head;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -1019,7 +1019,7 @@ static inline bool __attribute__((always_inline))
 	if (!dev)
 		return 0;
 
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
-- 
1.9.0

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

* [PATCH 10/17] vhost: export the number of vrings
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (8 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 09/17] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:33   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 11/17] vhost: move the device ready check at proper place Yuanhan Liu
                   ` (7 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_get_queue_num() for telling how many vrings.
However, the return value is the number of "queue pairs", which is
very virtio-net specific. To make it generic, we should return the
number of vrings instead, and let the driver do the proper translation.
Say, virtio-net driver could turn it to the number of queue pairs by
dividing 2.

Meanwhile, mark rte_vhost_get_queue_num as deprecated.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/vhost/rte_eth_vhost.c      |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 17 +++++++++++++++++
 lib/librte_vhost/vhost.c               | 11 +++++++++++
 4 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 816a9a0..135fec1 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -569,7 +569,7 @@ struct vhost_xstats_name_off {
 		vq->port = eth_dev->data->port_id;
 	}
 
-	for (i = 0; i < rte_vhost_get_queue_num(vid) * VIRTIO_QNUM; i++)
+	for (i = 0; i < rte_vhost_get_vring_num(vid); i++)
 		rte_vhost_enable_guest_notification(vid, i, 0);
 
 	eth_dev->data->dev_link.link_status = ETH_LINK_UP;
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 24f31ee..8e6290d 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -38,6 +38,7 @@ DPDK_17.05 {
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index dbdf004..280d9c2 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -163,17 +163,34 @@ int rte_vhost_driver_callback_register(const char *path,
 int rte_vhost_get_numa_node(int vid);
 
 /**
+ * @deprecated
  * Get the number of queues the device supports.
  *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
  * @param vid
  *  virtio-net device ID
  *
  * @return
  *  The number of queues, 0 on failure
  */
+__rte_deprecated
 uint32_t rte_vhost_get_queue_num(int vid);
 
 /**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
  * Get the virtio net device's ifname, which is the vhost-user socket
  * file path.
  *
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 82fb2b7..0a27888 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -296,6 +296,17 @@ struct virtio_net *
 	return dev->nr_vring / 2;
 }
 
+uint16_t
+rte_vhost_get_vring_num(int vid)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return 0;
+
+	return dev->nr_vring;
+}
+
 int
 rte_vhost_get_ifname(int vid, char *buf, size_t len)
 {
-- 
1.9.0

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

* [PATCH 11/17] vhost: move the device ready check at proper place
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (9 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 10/17] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:37   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 12/17] vhost: drop the Rx and Tx queue macro Yuanhan Liu
                   ` (6 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Currently, we check vq->desc, vq->kickfd and vq->callfd to know whether
a virtio device is ready or not. However, we only do it when handling
SET_VRING_KICK message, which could be wrong if a vhost-user frontend
send SET_VRING_KICK first and SET_VRING_CALL later.

To work for all possible vhost-user frontend implementations, we could
move the ready check at the end of vhost-user message handler.

Meanwhile, since we do the check more often than before, the "virtio
not ready" message is dropped, to not flood the screen.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/vhost_user.c | 32 ++++++++++++++------------------
 1 file changed, 14 insertions(+), 18 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index fdf6f62..2a49402 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -605,14 +605,14 @@
 	struct vhost_virtqueue *vq;
 	uint32_t i;
 
+	if (dev->nr_vring == 0)
+		return 0;
+
 	for (i = 0; i < dev->nr_vring; i++) {
 		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(vq)) {
-			RTE_LOG(INFO, VHOST_CONFIG,
-				"virtio is not ready for processing.\n");
+		if (!vq_is_ready(vq))
 			return 0;
-		}
 	}
 
 	RTE_LOG(INFO, VHOST_CONFIG,
@@ -641,10 +641,6 @@
 	vq->callfd = file.fd;
 }
 
-/*
- *  In vhost-user, when we receive kick message, will test whether virtio
- *  device is ready for packet processing.
- */
 static void
 vhost_user_set_vring_kick(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
@@ -663,16 +659,6 @@
 	if (vq->kickfd >= 0)
 		close(vq->kickfd);
 	vq->kickfd = file.fd;
-
-	if (virtio_is_ready(dev) && !(dev->flags & VIRTIO_DEV_RUNNING)) {
-		if (dev->dequeue_zero_copy) {
-			RTE_LOG(INFO, VHOST_CONFIG,
-				"dequeue zero copy is enabled\n");
-		}
-
-		if (dev->notify_ops->new_device(dev->vid) == 0)
-			dev->flags |= VIRTIO_DEV_RUNNING;
-	}
 }
 
 static void
@@ -1065,5 +1051,15 @@
 		send_vhost_message(fd, &msg);
 	}
 
+	if (!(dev->flags & VIRTIO_DEV_RUNNING) && virtio_is_ready(dev)) {
+		if (dev->dequeue_zero_copy) {
+			RTE_LOG(INFO, VHOST_CONFIG,
+				"dequeue zero copy is enabled\n");
+		}
+
+		if (dev->notify_ops->new_device(dev->vid) == 0)
+			dev->flags |= VIRTIO_DEV_RUNNING;
+	}
+
 	return 0;
 }
-- 
1.9.0

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

* [PATCH 12/17] vhost: drop the Rx and Tx queue macro
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (10 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 11/17] vhost: move the device ready check at proper place Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:42   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 13/17] vhost: do not include net specific headers Yuanhan Liu
                   ` (5 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

They are virti-net specific and should be defined inside the virtio-net
driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/vhost/rte_eth_vhost.c | 2 ++
 examples/tep_termination/main.h   | 2 ++
 examples/vhost/main.h             | 2 ++
 lib/librte_vhost/rte_virtio_net.h | 3 ---
 4 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 135fec1..450d167 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -45,6 +45,8 @@
 
 #include "rte_eth_vhost.h"
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 #define ETH_VHOST_IFACE_ARG		"iface"
 #define ETH_VHOST_QUEUES_ARG		"queues"
 #define ETH_VHOST_CLIENT_ARG		"client"
diff --git a/examples/tep_termination/main.h b/examples/tep_termination/main.h
index c0ea766..8ed817d 100644
--- a/examples/tep_termination/main.h
+++ b/examples/tep_termination/main.h
@@ -54,6 +54,8 @@
 /* Max number of devices. Limited by the application. */
 #define MAX_DEVICES 64
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 /* Per-device statistics struct */
 struct device_statistics {
 	uint64_t tx_total;
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 6bb42e8..7a3d251 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -41,6 +41,8 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 280d9c2..fa98d29 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -55,9 +55,6 @@
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
 #define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
 
-/* Enum for virtqueue management. */
-enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
-
 /**
  * Information relating to memory regions including offsets to
  * addresses in QEMUs memory file.
-- 
1.9.0

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

* [PATCH 13/17] vhost: do not include net specific headers
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (11 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 12/17] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:46   ` Maxime Coquelin
  2017-03-20  7:32   ` Liu, Changpeng
  2017-03-03  9:51 ` [PATCH 14/17] vhost: rename device ops struct Yuanhan Liu
                   ` (4 subsequent siblings)
  17 siblings, 2 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Include it internally, at vhost.h.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/vhost/main.h             | 2 ++
 lib/librte_vhost/rte_virtio_net.h | 4 ----
 lib/librte_vhost/vhost.h          | 4 ++++
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 7a3d251..ddcd858 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -36,6 +36,8 @@
 
 #include <sys/queue.h>
 
+#include <rte_ether.h>
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index fa98d29..e19ebad 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -42,14 +42,10 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 #include <linux/virtio_ring.h>
-#include <linux/virtio_net.h>
 #include <sys/eventfd.h>
-#include <sys/socket.h>
-#include <linux/if.h>
 
 #include <rte_memory.h>
 #include <rte_mempool.h>
-#include <rte_ether.h>
 
 #define RTE_VHOST_USER_CLIENT		(1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 829a45b..5bc0ebe 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -39,8 +39,12 @@
 #include <sys/queue.h>
 #include <unistd.h>
 #include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <sys/socket.h>
+#include <linux/if.h>
 
 #include <rte_log.h>
+#include <rte_ether.h>
 
 #include "rte_virtio_net.h"
 
-- 
1.9.0

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

* [PATCH 14/17] vhost: rename device ops struct
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (12 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 13/17] vhost: do not include net specific headers Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:48   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 15/17] vhost: rename virtio-net to vhost Yuanhan Liu
                   ` (3 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rename "virtio_net_device_ops" to "vhost_device_ops", to not let it
be virtio-net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 drivers/net/vhost/rte_eth_vhost.c | 2 +-
 examples/tep_termination/main.c   | 4 ++--
 examples/vhost/main.c             | 4 ++--
 lib/librte_vhost/Makefile         | 2 +-
 lib/librte_vhost/rte_virtio_net.h | 4 ++--
 lib/librte_vhost/socket.c         | 6 +++---
 lib/librte_vhost/vhost.h          | 4 ++--
 7 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 450d167..df1e386 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -669,7 +669,7 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-static struct virtio_net_device_ops vhost_ops = {
+static struct vhost_device_ops vhost_ops = {
 	.new_device          = new_device,
 	.destroy_device      = destroy_device,
 	.vring_state_changed = vring_state_changed,
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 03c0fbe..fa1c7a4 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1081,7 +1081,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops = {
+static const struct vhost_device_ops vhost_device_ops = {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
 };
@@ -1259,7 +1259,7 @@ static inline void __attribute__((always_inline))
 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
 	rte_vhost_driver_callback_register(dev_basename,
-		&virtio_net_device_ops);
+		&vhost_device_ops);
 
 	rte_vhost_driver_session_start();
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 867efc6..080c60b 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1270,7 +1270,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops =
+static const struct vhost_device_ops vhost_device_ops =
 {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
@@ -1540,7 +1540,7 @@ static inline void __attribute__((always_inline))
 		}
 
 		rte_vhost_driver_callback_register(file,
-			&virtio_net_device_ops);
+			&vhost_device_ops);
 	}
 
 	rte_vhost_driver_session_start();
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 415ffc6..5cf4e93 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -36,7 +36,7 @@ LIB = librte_vhost.a
 
 EXPORT_MAP := rte_vhost_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64
 CFLAGS += -I vhost_user
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index e19ebad..5cde87d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -87,7 +87,7 @@ struct rte_vhost_vring {
 /**
  * Device and vring operations.
  */
-struct virtio_net_device_ops {
+struct vhost_device_ops {
 	int (*new_device)(int vid);		/**< Add device. */
 	void (*destroy_device)(int vid);	/**< Remove device. */
 
@@ -139,7 +139,7 @@ static inline uint64_t __attribute__((always_inline))
 
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const);
+	struct vhost_device_ops const * const);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 550af64..c97559d 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -74,7 +74,7 @@ struct vhost_user_socket {
 	uint64_t supported_features;
 	uint64_t features;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -725,7 +725,7 @@ struct vhost_user_reconnect_list {
  */
 int
 rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops)
+	struct vhost_device_ops const * const ops)
 {
 	struct vhost_user_socket *vsocket;
 
@@ -738,7 +738,7 @@ struct vhost_user_reconnect_list {
 	return vsocket ? 0 : -1;
 }
 
-struct virtio_net_device_ops const *
+struct vhost_device_ops const *
 vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 5bc0ebe..fc9e431 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -183,7 +183,7 @@ struct virtio_net {
 	uint64_t		log_addr;
 	struct ether_addr	mac;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
@@ -257,7 +257,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
-struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+struct vhost_device_ops const *vhost_driver_callback_get(const char *path);
 
 /*
  * Backend-specific cleanup.
-- 
1.9.0

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

* [PATCH 15/17] vhost: rename virtio-net to vhost
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (13 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 14/17] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:50   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 16/17] vhost: rename header file Yuanhan Liu
                   ` (2 subsequent siblings)
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "virtio-net" to "vhost" in the API comments.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_virtio_net.h | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5cde87d..2f761da 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -148,7 +148,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * is allocated.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The numa node, -1 on failure
@@ -160,11 +160,11 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get the number of queues the device supports.
  *
  * Note this function is deprecated, as it returns a queue pair number,
- * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
  * be used.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The number of queues, 0 on failure
@@ -188,7 +188,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * file path.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param buf
  *  The buffer to stored the queried ifname
  * @param len
@@ -203,7 +203,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get how many avail entries are left in the queue
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index
  *
@@ -218,7 +218,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * count is returned to indicate the number of packets that were succesfully
  * added to the RX queue.
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param pkts
@@ -236,7 +236,7 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
  * construct host mbufs, copies guest buffer content to host mbufs and
  * store them in pkts to be processed.
  * @param vid
- *  virtio-net device
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param mbuf_pool
-- 
1.9.0

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

* [PATCH 16/17] vhost: rename header file
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (14 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 15/17] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-14 12:59   ` Maxime Coquelin
  2017-03-03  9:51 ` [PATCH 17/17] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
  17 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 doc/guides/rel_notes/deprecation.rst   |   9 --
 drivers/net/vhost/rte_eth_vhost.c      |   2 +-
 drivers/net/vhost/rte_eth_vhost.h      |   2 +-
 examples/tep_termination/main.c        |   2 +-
 examples/tep_termination/vxlan_setup.c |   2 +-
 examples/vhost/main.c                  |   2 +-
 lib/librte_vhost/Makefile              |   2 +-
 lib/librte_vhost/rte_vhost.h           | 259 +++++++++++++++++++++++++++++++++
 lib/librte_vhost/rte_virtio_net.h      | 259 ---------------------------------
 lib/librte_vhost/vhost.c               |   2 +-
 lib/librte_vhost/vhost.h               |   2 +-
 lib/librte_vhost/vhost_user.h          |   2 +-
 lib/librte_vhost/virtio_net.c          |   2 +-
 13 files changed, 269 insertions(+), 278 deletions(-)
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index 9d4dfcc..84c8b9d 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -104,15 +104,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* vhost: API/ABI changes are planned for 17.05, for making DPDK vhost library
-  generic enough so that applications can build different vhost-user drivers
-  (instead of vhost-user net only) on top of that.
-  Specifically, ``virtio_net_device_ops`` will be renamed to ``vhost_device_ops``.
-  Correspondingly, some API's parameter need be changed. Few more functions also
-  need be reworked to let it be device aware. For example, different virtio device
-  has different feature set, meaning functions like ``rte_vhost_feature_disable``
-  need be changed. Last, file rte_virtio_net.h will be renamed to rte_vhost.h.
-
 * kni: Remove :ref:`kni_vhost_backend-label` feature (KNI_VHOST) in 17.05 release.
   :doc:`Vhost Library </prog_guide/vhost_lib>` is currently preferred method for
   guest - host communication. Just for clarification, this is not to remove KNI
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index df1e386..f7c370e 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -40,7 +40,7 @@
 #include <rte_memcpy.h>
 #include <rte_vdev.h>
 #include <rte_kvargs.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_spinlock.h>
 
 #include "rte_eth_vhost.h"
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index ea4bce4..39ca771 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -41,7 +41,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 /*
  * Event description.
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index fa1c7a4..63a5dd3 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "main.h"
 #include "vxlan.h"
diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c
index 8f1f15b..87de74d 100644
--- a/examples/tep_termination/vxlan_setup.c
+++ b/examples/tep_termination/vxlan_setup.c
@@ -49,7 +49,7 @@
 #include <rte_tcp.h>
 
 #include "main.h"
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 #include "vxlan.h"
 #include "vxlan_setup.h"
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 080c60b..a9b5352 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_ip.h>
 #include <rte_tcp.h>
 
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 5cf4e93..4847069 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -51,7 +51,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := fd_man.c socket.c vhost.c vhost_user.c \
 				   virtio_net.c
 
 # install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_vhost.h
 
 # dependencies
 DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_eal
diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
new file mode 100644
index 0000000..cfb3507
--- /dev/null
+++ b/lib/librte_vhost/rte_vhost.h
@@ -0,0 +1,259 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_VHOST_H_
+#define _RTE_VHOST_H_
+
+/**
+ * @file
+ * Interface to vhost-user
+ */
+
+#include <stdint.h>
+#include <linux/vhost.h>
+#include <linux/virtio_ring.h>
+#include <sys/eventfd.h>
+
+#include <rte_memory.h>
+#include <rte_mempool.h>
+
+#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
+#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
+#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
+
+/**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
+/**
+ * Device and vring operations.
+ */
+struct vhost_device_ops {
+	int (*new_device)(int vid);		/**< Add device. */
+	void (*destroy_device)(int vid);	/**< Remove device. */
+
+	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
+
+	void *reserved[5]; /**< Reserved for future extension */
+};
+
+/**
+ * Convert guest physical Address to host virtual address
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
+int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
+
+/**
+ * Register vhost driver. path could be different for multiple
+ * instance support.
+ */
+int rte_vhost_driver_register(const char *path, uint64_t flags);
+
+/* Unregister vhost driver. This is only meaningful to vhost user. */
+int rte_vhost_driver_unregister(const char *path);
+
+/**
+ * Set feature bits the vhost driver supports.
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+uint64_t rte_vhost_driver_get_features(const char *path);
+
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/* Register callbacks. */
+int rte_vhost_driver_callback_register(const char *path,
+	struct vhost_device_ops const * const);
+/* Start vhost driver session blocking loop. */
+int rte_vhost_driver_session_start(void);
+
+/**
+ * Get the numa node from which the virtio net device's memory
+ * is allocated.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The numa node, -1 on failure
+ */
+int rte_vhost_get_numa_node(int vid);
+
+/**
+ * @deprecated
+ * Get the number of queues the device supports.
+ *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of queues, 0 on failure
+ */
+__rte_deprecated
+uint32_t rte_vhost_get_queue_num(int vid);
+
+/**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
+ * Get the virtio net device's ifname, which is the vhost-user socket
+ * file path.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param buf
+ *  The buffer to stored the queried ifname
+ * @param len
+ *  The length of buf
+ *
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_ifname(int vid, char *buf, size_t len);
+
+/**
+ * Get how many avail entries are left in the queue
+ *
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index
+ *
+ * @return
+ *  num of avail entires left
+ */
+uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
+
+/**
+ * This function adds buffers to the virtio devices RX virtqueue. Buffers can
+ * be received from the physical port or from another virtual device. A packet
+ * count is returned to indicate the number of packets that were succesfully
+ * added to the RX queue.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param pkts
+ *  array to contain packets to be enqueued
+ * @param count
+ *  packets num to be enqueued
+ * @return
+ *  num of packets enqueued
+ */
+uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
+	struct rte_mbuf **pkts, uint16_t count);
+
+/**
+ * This function gets guest buffers from the virtio device TX virtqueue,
+ * construct host mbufs, copies guest buffer content to host mbufs and
+ * store them in pkts to be processed.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param mbuf_pool
+ *  mbuf_pool where host mbuf is allocated.
+ * @param pkts
+ *  array to contain packets to be dequeued
+ * @param count
+ *  packets num to be dequeued
+ * @return
+ *  num of packets dequeued
+ */
+uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
+
+int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
+uint64_t rte_vhost_get_negotiated_features(int vid);
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
+#endif /* _RTE_VHOST_H_ */
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
deleted file mode 100644
index 2f761da..0000000
--- a/lib/librte_vhost/rte_virtio_net.h
+++ /dev/null
@@ -1,259 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _VIRTIO_NET_H_
-#define _VIRTIO_NET_H_
-
-/**
- * @file
- * Interface to vhost net
- */
-
-#include <stdint.h>
-#include <linux/vhost.h>
-#include <linux/virtio_ring.h>
-#include <sys/eventfd.h>
-
-#include <rte_memory.h>
-#include <rte_mempool.h>
-
-#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
-#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
-#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
-
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct rte_vhost_mem_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct rte_vhost_memory {
-	uint32_t nregions;
-	struct rte_vhost_mem_region regions[0];
-};
-
-struct rte_vhost_vring {
-	struct vring_desc	*desc;
-	struct vring_avail	*avail;
-	struct vring_used	*used;
-	uint64_t		log_guest_addr;
-
-	int			callfd;
-	int			kickfd;
-	uint16_t		size;
-};
-
-/**
- * Device and vring operations.
- */
-struct vhost_device_ops {
-	int (*new_device)(int vid);		/**< Add device. */
-	void (*destroy_device)(int vid);	/**< Remove device. */
-
-	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
-
-	void *reserved[5]; /**< Reserved for future extension */
-};
-
-/**
- * Convert guest physical Address to host virtual address
- */
-static inline uint64_t __attribute__((always_inline))
-rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < mem->nregions; i++) {
-		reg = &mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
-int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
-
-/**
- * Register vhost driver. path could be different for multiple
- * instance support.
- */
-int rte_vhost_driver_register(const char *path, uint64_t flags);
-
-/* Unregister vhost driver. This is only meaningful to vhost user. */
-int rte_vhost_driver_unregister(const char *path);
-
-/**
- * Set feature bits the vhost driver supports.
- */
-int rte_vhost_driver_set_features(const char *path, uint64_t features);
-uint64_t rte_vhost_driver_get_features(const char *path);
-
-int rte_vhost_driver_enable_features(const char *path, uint64_t features);
-int rte_vhost_driver_disable_features(const char *path, uint64_t features);
-
-/* Register callbacks. */
-int rte_vhost_driver_callback_register(const char *path,
-	struct vhost_device_ops const * const);
-/* Start vhost driver session blocking loop. */
-int rte_vhost_driver_session_start(void);
-
-/**
- * Get the numa node from which the virtio net device's memory
- * is allocated.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The numa node, -1 on failure
- */
-int rte_vhost_get_numa_node(int vid);
-
-/**
- * @deprecated
- * Get the number of queues the device supports.
- *
- * Note this function is deprecated, as it returns a queue pair number,
- * which is vhost specific. Instead, rte_vhost_get_vring_num should
- * be used.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of queues, 0 on failure
- */
-__rte_deprecated
-uint32_t rte_vhost_get_queue_num(int vid);
-
-/**
- * Get the number of vrings the device supports.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of vrings, 0 on failure
- */
-uint16_t rte_vhost_get_vring_num(int vid);
-
-/**
- * Get the virtio net device's ifname, which is the vhost-user socket
- * file path.
- *
- * @param vid
- *  vhost device ID
- * @param buf
- *  The buffer to stored the queried ifname
- * @param len
- *  The length of buf
- *
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_ifname(int vid, char *buf, size_t len);
-
-/**
- * Get how many avail entries are left in the queue
- *
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index
- *
- * @return
- *  num of avail entires left
- */
-uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
-
-/**
- * This function adds buffers to the virtio devices RX virtqueue. Buffers can
- * be received from the physical port or from another virtual device. A packet
- * count is returned to indicate the number of packets that were succesfully
- * added to the RX queue.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param pkts
- *  array to contain packets to be enqueued
- * @param count
- *  packets num to be enqueued
- * @return
- *  num of packets enqueued
- */
-uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
-	struct rte_mbuf **pkts, uint16_t count);
-
-/**
- * This function gets guest buffers from the virtio device TX virtqueue,
- * construct host mbufs, copies guest buffer content to host mbufs and
- * store them in pkts to be processed.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param mbuf_pool
- *  mbuf_pool where host mbuf is allocated.
- * @param pkts
- *  array to contain packets to be dequeued
- * @param count
- *  packets num to be dequeued
- * @return
- *  num of packets dequeued
- */
-uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
-	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
-
-int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
-uint64_t rte_vhost_get_negotiated_features(int vid);
-int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
-			      struct rte_vhost_vring *vring);
-
-#endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 0a27888..e0548fe 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -45,7 +45,7 @@
 #include <rte_string_fns.h>
 #include <rte_memory.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "vhost.h"
 
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index fc9e431..29132f3 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -46,7 +46,7 @@
 #include <rte_log.h>
 #include <rte_ether.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 #define VHOST_USER_F_PROTOCOL_FEATURES	30
 
diff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h
index 179e441..f1a7823 100644
--- a/lib/librte_vhost/vhost_user.h
+++ b/lib/librte_vhost/vhost_user.h
@@ -37,7 +37,7 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* refer to hw/virtio/vhost-user.c */
 
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 8ed2b93..6287c7a 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -39,7 +39,7 @@
 #include <rte_memcpy.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_sctp.h>
-- 
1.9.0

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

* [PATCH 17/17] examples/vhost: demonstrate the new generic vhost APIs
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (15 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 16/17] vhost: rename header file Yuanhan Liu
@ 2017-03-03  9:51 ` Yuanhan Liu
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
  17 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-03  9:51 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Now DPDK vhost lib has been generic enough, that it can be used to
implement any vhost-user drivers.

For example, this patch implements a very simple vhost-user net driver,
mainly for demonstrating how to use those generic vhost APIs.

And when the --builtin-net-driver option is used, the example virtio-net
driver code will be invoked, instead of the one provided from the vhost
library.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/vhost/Makefile     |   2 +-
 examples/vhost/main.c       |  36 +++-
 examples/vhost/main.h       |  29 +++-
 examples/vhost/virtio_net.c | 405 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 465 insertions(+), 7 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c

diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile
index e95c68a..af7be99 100644
--- a/examples/vhost/Makefile
+++ b/examples/vhost/Makefile
@@ -48,7 +48,7 @@ else
 APP = vhost-switch
 
 # all source are stored in SRCS-y
-SRCS-y := main.c
+SRCS-y := main.c virtio_net.c
 
 CFLAGS += -O2 -D_FILE_OFFSET_BITS=64
 CFLAGS += $(WERROR_FLAGS)
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index a9b5352..bebfb7f 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,6 @@
 #define MBUF_CACHE_SIZE	128
 #define MBUF_DATA_SIZE	RTE_MBUF_DEFAULT_BUF_SIZE
 
-#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
 #define BURST_TX_DRAIN_US 100	/* TX drain every ~100us */
 
 #define BURST_RX_WAIT_US 15	/* Defines how long we wait between retries on RX */
@@ -129,6 +128,8 @@
 static int client_mode;
 static int dequeue_zero_copy;
 
+static int builtin_net_driver;
+
 /* Specify timeout (in useconds) between retries on RX. */
 static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
 /* Specify the number of retries on RX. */
@@ -499,6 +500,7 @@ struct mbuf_table {
 		{"tso", required_argument, NULL, 0},
 		{"client", no_argument, &client_mode, 1},
 		{"dequeue-zero-copy", no_argument, &dequeue_zero_copy, 1},
+		{"builtin-net-driver", no_argument, &builtin_net_driver, 1},
 		{NULL, 0, 0, 0},
 	};
 
@@ -795,7 +797,12 @@ static inline void __attribute__((always_inline))
 {
 	uint16_t ret;
 
-	ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	if (builtin_net_driver) {
+		ret = vs_enqueue_pkts(dst_vdev, VIRTIO_RXQ, &m, 1);
+	} else {
+		ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	}
+
 	if (enable_stats) {
 		rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
 		rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
@@ -1066,8 +1073,13 @@ static inline void __attribute__((always_inline))
 		}
 	}
 
-	enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+	if (builtin_net_driver) {
+		enqueue_count = vs_enqueue_pkts(vdev, VIRTIO_RXQ,
 						pkts, rx_count);
+	} else {
+		enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+						pkts, rx_count);
+	}
 	if (enable_stats) {
 		rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
 		rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
@@ -1083,8 +1095,13 @@ static inline void __attribute__((always_inline))
 	uint16_t count;
 	uint16_t i;
 
-	count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
+	if (builtin_net_driver) {
+		count = vs_dequeue_pkts(vdev, VIRTIO_TXQ, mbuf_pool,
 					pkts, MAX_PKT_BURST);
+	} else {
+		count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ,
+					mbuf_pool, pkts, MAX_PKT_BURST);
+	}
 
 	/* setup VMDq for the first packet */
 	if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
@@ -1187,6 +1204,9 @@ static inline void __attribute__((always_inline))
 		rte_pause();
 	}
 
+	if (builtin_net_driver)
+		vs_vhost_net_remove(vdev);
+
 	TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
 		     lcore_vdev_entry);
 	TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
@@ -1235,6 +1255,9 @@ static inline void __attribute__((always_inline))
 	}
 	vdev->vid = vid;
 
+	if (builtin_net_driver)
+		vs_vhost_net_setup(vdev);
+
 	TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
 	vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
 
@@ -1513,6 +1536,9 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+
+		ret = rte_vhost_driver_set_features(file, VIRTIO_NET_FEATURES);
+
 		if (mergeable == 0) {
 			rte_vhost_driver_disable_features(file,
 				1ULL << VIRTIO_NET_F_MRG_RXBUF);
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index ddcd858..5ba7d38 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -43,8 +43,11 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
+#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
@@ -52,6 +55,12 @@ struct device_statistics {
 	rte_atomic64_t	rx_total_atomic;
 };
 
+struct vhost_queue {
+	struct rte_vhost_vring	vr;
+	uint16_t		last_avail_idx;
+	uint16_t		last_used_idx;
+};
+
 struct vhost_dev {
 	/**< Number of memory regions for gpa to hpa translation. */
 	uint32_t nregions_hpa;
@@ -69,9 +78,16 @@ struct vhost_dev {
 	volatile uint8_t remove;
 
 	int vid;
+	uint64_t features;
+	size_t hdr_len;
+	uint16_t nr_vrings;
+	struct rte_vhost_memory *mem;
 	struct device_statistics stats;
 	TAILQ_ENTRY(vhost_dev) global_vdev_entry;
 	TAILQ_ENTRY(vhost_dev) lcore_vdev_entry;
+
+#define MAX_QUEUE_PAIRS	4
+	struct vhost_queue queues[MAX_QUEUE_PAIRS * 2];
 } __rte_cache_aligned;
 
 TAILQ_HEAD(vhost_dev_tailq_list, vhost_dev);
@@ -92,4 +108,15 @@ struct lcore_info {
 	struct vhost_dev_tailq_list vdev_list;
 };
 
+/* we implement non-extra virtio net features */
+#define VIRTIO_NET_FEATURES	0
+
+void vs_vhost_net_setup(struct vhost_dev *dev);
+void vs_vhost_net_remove(struct vhost_dev *dev);
+uint16_t vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mbuf **pkts, uint32_t count);
+
+uint16_t vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mempool *mbuf_pool,
+			 struct rte_mbuf **pkts, uint16_t count);
 #endif /* _MAIN_H_ */
diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c
new file mode 100644
index 0000000..6dbf8aa
--- /dev/null
+++ b/examples/vhost/virtio_net.c
@@ -0,0 +1,405 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <linux/virtio_net.h>
+
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_vhost.h>
+
+#include "main.h"
+
+/*
+ * A very simple vhost-user net driver implementation, without
+ * any extra features being enabled, such as TSO and mrg-Rx.
+ */
+
+void
+vs_vhost_net_setup(struct vhost_dev *dev)
+{
+	uint16_t i;
+	int vid = dev->vid;
+	struct vhost_queue *queue;
+
+	RTE_LOG(INFO, VHOST_CONFIG,
+		"setting builtin vhost-user net driver\n");
+
+	dev->features = rte_vhost_get_negotiated_features(vid);
+	if (dev->features &
+		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
+		dev->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+	} else {
+		dev->hdr_len = sizeof(struct virtio_net_hdr);
+	}
+
+	rte_vhost_get_vhost_memory(vid, &dev->mem);
+
+	dev->nr_vrings = rte_vhost_get_vring_num(vid);
+	for (i = 0; i < dev->nr_vrings; i++) {
+		queue = &dev->queues[i];
+
+		queue->last_used_idx  = 0;
+		queue->last_avail_idx = 0;
+		rte_vhost_get_vhost_vring(vid, i, &queue->vr);
+	}
+}
+
+void
+vs_vhost_net_remove(struct vhost_dev *dev)
+{
+	free(dev->mem);
+}
+
+static inline int __attribute__((always_inline))
+enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx)
+{
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
+	/* A counter to avoid desc dead loop chain */
+	uint16_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	/*
+	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
+	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
+	 * otherwise stores offset on the stack instead of in a register.
+	 */
+	if (unlikely(desc->len < dev->hdr_len) || !desc_addr)
+		return -1;
+
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	/* write virtio-net header */
+	*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+
+	desc_offset = dev->hdr_len;
+	desc_avail  = desc->len - dev->hdr_len;
+
+	mbuf_avail  = rte_pktmbuf_data_len(m);
+	mbuf_offset = 0;
+	while (mbuf_avail != 0 || m->next != NULL) {
+		/* done with current mbuf, fetch next */
+		if (mbuf_avail == 0) {
+			m = m->next;
+
+			mbuf_offset = 0;
+			mbuf_avail  = rte_pktmbuf_data_len(m);
+		}
+
+		/* done with current desc buf, fetch next */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0) {
+				/* Room in vring buffer is not enough */
+				return -1;
+			}
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+
+			desc = &vr->desc[desc->next];
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
+			rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+	}
+
+	return 0;
+}
+
+uint16_t
+vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+		struct rte_mbuf **pkts, uint32_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint16_t avail_idx, free_entries, start_idx;
+	uint16_t desc_indexes[MAX_PKT_BURST];
+	uint16_t used_idx;
+	uint32_t i;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	avail_idx = *((volatile uint16_t *)&vr->avail->idx);
+	start_idx = queue->last_used_idx;
+	free_entries = avail_idx - start_idx;
+	count = RTE_MIN(count, free_entries);
+	count = RTE_MIN(count, (uint32_t)MAX_PKT_BURST);
+	if (count == 0)
+		return 0;
+
+	/* Retrieve all of the desc indexes first to avoid caching issues. */
+	rte_prefetch0(&vr->avail->ring[start_idx & (vr->size - 1)]);
+	for (i = 0; i < count; i++) {
+		used_idx = (start_idx + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[used_idx];
+		vr->used->ring[used_idx].id = desc_indexes[i];
+		vr->used->ring[used_idx].len = pkts[i]->pkt_len +
+					       dev->hdr_len;
+	}
+
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		uint16_t desc_idx = desc_indexes[i];
+		int err;
+
+		err = enqueue_pkt(dev, vr, pkts[i], desc_idx);
+		if (unlikely(err)) {
+			used_idx = (start_idx + i) & (vr->size - 1);
+			vr->used->ring[used_idx].len = dev->hdr_len;
+		}
+
+		if (i + 1 < count)
+			rte_prefetch0(&vr->desc[desc_indexes[i+1]]);
+	}
+
+	rte_smp_wmb();
+
+	*(volatile uint16_t *)&vr->used->idx += count;
+	queue->last_used_idx += count;
+
+	/* flush used->idx update before we read avail->flags. */
+	rte_mb();
+
+	/* Kick the guest if necessary. */
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+	return count;
+}
+
+static inline int __attribute__((always_inline))
+dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx,
+	    struct rte_mempool *mbuf_pool)
+{
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct rte_mbuf *cur = m, *prev = m;
+	/* A counter to avoid desc dead loop chain */
+	uint32_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	if (unlikely((desc->len < dev->hdr_len)) ||
+			(desc->flags & VRING_DESC_F_INDIRECT))
+		return -1;
+
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+
+	/*
+	 * We don't support ANY_LAYOUT, neither VERSION_1, meaning
+	 * a Tx packet from guest must have 2 desc buffers at least:
+	 * the first for storing the header and the others for
+	 * storing the data.
+	 *
+	 * And since we don't support TSO, we could simply skip the
+	 * header.
+	 */
+	desc = &vr->desc[desc->next];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	desc_offset = 0;
+	desc_avail  = desc->len;
+	nr_desc    += 1;
+
+	mbuf_offset = 0;
+	mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
+	while (1) {
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
+						   mbuf_offset),
+			(void *)((uintptr_t)(desc_addr + desc_offset)),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+
+		/* This desc reaches to its end, get the next one */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0)
+				break;
+
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+			desc = &vr->desc[desc->next];
+
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+			rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		/*
+		 * This mbuf reaches to its end, get a new one
+		 * to hold more data.
+		 */
+		if (mbuf_avail == 0) {
+			cur = rte_pktmbuf_alloc(mbuf_pool);
+			if (unlikely(cur == NULL)) {
+				RTE_LOG(ERR, VHOST_DATA, "Failed to "
+					"allocate memory for mbuf.\n");
+				return -1;
+			}
+
+			prev->next = cur;
+			prev->data_len = mbuf_offset;
+			m->nb_segs += 1;
+			m->pkt_len += mbuf_offset;
+			prev = cur;
+
+			mbuf_offset = 0;
+			mbuf_avail  = cur->buf_len - RTE_PKTMBUF_HEADROOM;
+		}
+	}
+
+	prev->data_len = mbuf_offset;
+	m->pkt_len    += mbuf_offset;
+
+	return 0;
+}
+
+uint16_t
+vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint32_t desc_indexes[MAX_PKT_BURST];
+	uint32_t used_idx;
+	uint32_t i = 0;
+	uint16_t free_entries;
+	uint16_t avail_idx;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	free_entries = *((volatile uint16_t *)&vr->avail->idx) -
+			queue->last_avail_idx;
+	if (free_entries == 0)
+		return 0;
+
+	/* Prefetch available and used ring */
+	avail_idx = queue->last_avail_idx & (vr->size - 1);
+	used_idx  = queue->last_used_idx  & (vr->size - 1);
+	rte_prefetch0(&vr->avail->ring[avail_idx]);
+	rte_prefetch0(&vr->used->ring[used_idx]);
+
+	count = RTE_MIN(count, MAX_PKT_BURST);
+	count = RTE_MIN(count, free_entries);
+
+	/*
+	 * Retrieve all of the head indexes first and pre-update used entries
+	 * to avoid caching issues.
+	 */
+	for (i = 0; i < count; i++) {
+		avail_idx = (queue->last_avail_idx + i) & (vr->size - 1);
+		used_idx  = (queue->last_used_idx  + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[avail_idx];
+
+		vr->used->ring[used_idx].id  = desc_indexes[i];
+		vr->used->ring[used_idx].len = 0;
+	}
+
+	/* Prefetch descriptor index. */
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		int err;
+
+		if (likely(i + 1 < count))
+			rte_prefetch0(&vr->desc[desc_indexes[i + 1]]);
+
+		pkts[i] = rte_pktmbuf_alloc(mbuf_pool);
+		if (unlikely(pkts[i] == NULL)) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed to allocate memory for mbuf.\n");
+			break;
+		}
+
+		err = dequeue_pkt(dev, vr, pkts[i], desc_indexes[i], mbuf_pool);
+		if (unlikely(err)) {
+			rte_pktmbuf_free(pkts[i]);
+			break;
+		}
+
+	}
+	if (!i)
+		return 0;
+
+	queue->last_avail_idx += i;
+	queue->last_used_idx += i;
+	rte_smp_wmb();
+	rte_smp_rmb();
+
+	vr->used->idx += i;
+
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+
+	return i;
+}
-- 
1.9.0

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

* Re: [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-03  9:51 ` [PATCH 01/17] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-14  9:46   ` Maxime Coquelin
  2017-03-14  9:53     ` Maxime Coquelin
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14  9:46 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Introduce few APIs to set/get/enable/disable driver features.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map | 10 ++++
>  lib/librte_vhost/rte_virtio_net.h      |  9 ++++
>  lib/librte_vhost/socket.c              | 90 ++++++++++++++++++++++++++++++++++
>  3 files changed, 109 insertions(+)

Nice!
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

I wonder whether we could protect from setting/enabling/disabling
features once negotiation is done?

Thanks,
Maxime

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

* Re: [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-14  9:46   ` Maxime Coquelin
@ 2017-03-14  9:53     ` Maxime Coquelin
  2017-03-16  7:08       ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14  9:53 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/14/2017 10:46 AM, Maxime Coquelin wrote:
>
>
> On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
>> Introduce few APIs to set/get/enable/disable driver features.
>>
>> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
>> ---
>>  lib/librte_vhost/rte_vhost_version.map | 10 ++++
>>  lib/librte_vhost/rte_virtio_net.h      |  9 ++++
>>  lib/librte_vhost/socket.c              | 90
>> ++++++++++++++++++++++++++++++++++
>>  3 files changed, 109 insertions(+)
>
> Nice!
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
>
> I wonder whether we could protect from setting/enabling/disabling
> features once negotiation is done?

Oh, I forgot one comment on this patch.
Since these new functions are part to the API, shouldn't them be
documented?

Maxime

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

* Re: [PATCH 02/17] net/vhost: remove feature related APIs
  2017-03-03  9:51 ` [PATCH 02/17] net/vhost: remove feature " Yuanhan Liu
@ 2017-03-14 10:15   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 10:15 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> vdev options is better for disabling/enabling some features.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  drivers/net/vhost/rte_eth_vhost.c           | 25 ------------------------
>  drivers/net/vhost/rte_eth_vhost.h           | 30 -----------------------------
>  drivers/net/vhost/rte_pmd_vhost_version.map |  3 ---
>  3 files changed, 58 deletions(-)

Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 03/17] vhost: use new APIs to handle features
  2017-03-03  9:51 ` [PATCH 03/17] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-03-14 10:43   ` Maxime Coquelin
  2017-03-16  7:43     ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 10:43 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  examples/tep_termination/main.c        |  4 +++-
>  examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
>  lib/librte_vhost/rte_vhost_version.map |  3 ---
>  lib/librte_vhost/rte_virtio_net.h      | 13 ----------
>  lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
>  lib/librte_vhost/vhost.c               | 41 --------------------------------
>  lib/librte_vhost/vhost.h               | 20 ++++++++++++++++
>  lib/librte_vhost/vhost_user.c          |  8 +++----
>  8 files changed, 76 insertions(+), 79 deletions(-)
>

</snip>

>
> diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
> index 8433a54..f7227bf 100644
> --- a/lib/librte_vhost/vhost_user.c
> +++ b/lib/librte_vhost/vhost_user.c
> @@ -143,9 +143,9 @@
>   * The features that we support are requested.
>   */
>  static uint64_t
> -vhost_user_get_features(void)
> +vhost_user_get_features(struct virtio_net *dev)
>  {
> -	return VHOST_FEATURES;
> +	return rte_vhost_driver_get_features(dev->ifname);
>  }
>
>  /*
> @@ -154,7 +154,7 @@
>  static int
>  vhost_user_set_features(struct virtio_net *dev, uint64_t features)
>  {
> -	if (features & ~VHOST_FEATURES)
> +	if (features & ~rte_vhost_driver_get_features(dev->ifname))

rte_vhost_driver_get_features() returns -1 if the socket is not found.
It would result in accepting any feature trying to be set.

Maxime

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

* Re: [PATCH 04/17] vhost: make notify ops per vhost driver
  2017-03-03  9:51 ` [PATCH 04/17] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-03-14 10:55   ` Maxime Coquelin
  2017-03-16  7:50     ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 10:55 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Assume there is an application both support vhost-user net and
> vhost-user scsi, the callback should be different. Making notify
> ops per vhost driver allow application define different set of
> callbacks for different driver.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  drivers/net/vhost/rte_eth_vhost.c | 20 +++++++++++---------
>  examples/tep_termination/main.c   |  3 ++-
>  examples/vhost/main.c             |  5 +++--
>  lib/librte_vhost/rte_virtio_net.h |  3 ++-
>  lib/librte_vhost/socket.c         | 32 ++++++++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.c          | 16 +---------------
>  lib/librte_vhost/vhost.h          |  5 ++++-
>  lib/librte_vhost/vhost_user.c     | 15 +++++++++------
>  8 files changed, 64 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
> index 0ebaa4a..816a9a0 100644
> --- a/drivers/net/vhost/rte_eth_vhost.c
> +++ b/drivers/net/vhost/rte_eth_vhost.c
> @@ -667,6 +667,12 @@ struct vhost_xstats_name_off {
>  	return 0;
>  }
>
> +static struct virtio_net_device_ops vhost_ops = {
> +	.new_device          = new_device,
> +	.destroy_device      = destroy_device,
> +	.vring_state_changed = vring_state_changed,
> +};
> +
>  int
>  rte_eth_vhost_get_queue_event(uint8_t port_id,
>  		struct rte_eth_vhost_queue_event *event)
> @@ -736,15 +742,6 @@ struct vhost_xstats_name_off {
>  static void *
>  vhost_driver_session(void *param __rte_unused)
>  {
> -	static struct virtio_net_device_ops vhost_ops;
> -
> -	/* set vhost arguments */
> -	vhost_ops.new_device = new_device;
> -	vhost_ops.destroy_device = destroy_device;
> -	vhost_ops.vring_state_changed = vring_state_changed;
> -	if (rte_vhost_driver_callback_register(&vhost_ops) < 0)
> -		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
> -
>  	/* start event handling */
>  	rte_vhost_driver_session_start();
>
> @@ -1077,6 +1074,11 @@ struct vhost_xstats_name_off {
>  	if (rte_vhost_driver_register(iface_name, flags))
>  		goto error;
>
> +	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
> +		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
> +		goto error;
> +	}
> +
>  	/* We need only one message handling thread */
>  	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
>  		if (vhost_driver_session_start())
> diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
> index 8c45128..03c0fbe 100644
> --- a/examples/tep_termination/main.c
> +++ b/examples/tep_termination/main.c
> @@ -1258,7 +1258,8 @@ static inline void __attribute__((always_inline))
>  	rte_vhost_driver_disable_features(dev_basename,
>  		1ULL << VIRTIO_NET_F_MRG_RXBUF);
>
> -	rte_vhost_driver_callback_register(&virtio_net_device_ops);
> +	rte_vhost_driver_callback_register(dev_basename,
> +		&virtio_net_device_ops);

Return should be checked here, as this function can now return -1.

>
>  	rte_vhost_driver_session_start();
>
> diff --git a/examples/vhost/main.c b/examples/vhost/main.c
> index 972a6a8..867efc6 100644
> --- a/examples/vhost/main.c
> +++ b/examples/vhost/main.c
> @@ -1538,9 +1538,10 @@ static inline void __attribute__((always_inline))
>  			rte_vhost_driver_enable_features(file,
>  				1ULL << VIRTIO_NET_F_CTRL_RX);
>  		}
> -	}
>
> -	rte_vhost_driver_callback_register(&virtio_net_device_ops);
> +		rte_vhost_driver_callback_register(file,
> +			&virtio_net_device_ops);
> +	}

Ditto.

>
>  	rte_vhost_driver_session_start();
>  	return 0;
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index 51f5166..3bfd0b7 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -91,7 +91,8 @@ struct virtio_net_device_ops {
>  int rte_vhost_driver_disable_features(const char *path, uint64_t features);
>
>  /* Register callbacks. */
> -int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
> +int rte_vhost_driver_callback_register(const char *path,
> +	struct virtio_net_device_ops const * const);
>  /* Start vhost driver session blocking loop. */
>  int rte_vhost_driver_session_start(void);
>
> diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
> index 9e0ec05..550af64 100644
> --- a/lib/librte_vhost/socket.c
> +++ b/lib/librte_vhost/socket.c
> @@ -73,6 +73,8 @@ struct vhost_user_socket {
>  	 */
>  	uint64_t supported_features;
>  	uint64_t features;
> +
> +	struct virtio_net_device_ops const *notify_ops;
>  };
>
>  struct vhost_user_connection {
> @@ -718,6 +720,36 @@ struct vhost_user_reconnect_list {
>  	return -1;
>  }
>
> +/*
> + * Register ops so that we can add/remove device to data core.
> + */
> +int
> +rte_vhost_driver_callback_register(const char *path,
> +	struct virtio_net_device_ops const * const ops)
> +{
> +	struct vhost_user_socket *vsocket;
> +
> +	pthread_mutex_lock(&vhost_user.mutex);
> +	vsocket = find_vhost_user_socket(path);
> +	if (vsocket)
> +		vsocket->notify_ops = ops;
> +	pthread_mutex_unlock(&vhost_user.mutex);
> +
> +	return vsocket ? 0 : -1;
> +}
> +
> +struct virtio_net_device_ops const *
> +vhost_driver_callback_get(const char *path)
> +{
> +	struct vhost_user_socket *vsocket;
> +
> +	pthread_mutex_lock(&vhost_user.mutex);
> +	vsocket = find_vhost_user_socket(path);
> +	pthread_mutex_unlock(&vhost_user.mutex);
> +
> +	return vsocket->notify_ops;

There should be a check against vsocket to avoid NULL pointer
dereferencing.

> +}
> +
>  int
>  rte_vhost_driver_session_start(void)
>  {
> diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
> index 2790f17..0088f87 100644
> --- a/lib/librte_vhost/vhost.c
> +++ b/lib/librte_vhost/vhost.c
> @@ -51,9 +51,6 @@
>
>  struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
>
> -/* device ops to add/remove device to/from data core. */
> -struct virtio_net_device_ops const *notify_ops;
> -
>  struct virtio_net *
>  get_device(int vid)
>  {
> @@ -253,7 +250,7 @@ struct virtio_net *
>
>  	if (dev->flags & VIRTIO_DEV_RUNNING) {
>  		dev->flags &= ~VIRTIO_DEV_RUNNING;
> -		notify_ops->destroy_device(vid);
> +		dev->notify_ops->destroy_device(vid);
>  	}
>
>  	cleanup_device(dev, 1);
> @@ -377,14 +374,3 @@ struct virtio_net *
>  	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
>  	return 0;
>  }
> -
> -/*
> - * Register ops so that we can add/remove device to data core.
> - */
> -int
> -rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
> -{
> -	notify_ops = ops;
> -
> -	return 0;
> -}
> diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
> index 61e7448..bc03e09 100644
> --- a/lib/librte_vhost/vhost.h
> +++ b/lib/librte_vhost/vhost.h
> @@ -177,6 +177,8 @@ struct virtio_net {
>  	uint64_t		log_addr;
>  	struct ether_addr	mac;
>
> +	struct virtio_net_device_ops const *notify_ops;
> +
>  	uint32_t		nr_guest_pages;
>  	uint32_t		max_guest_pages;
>  	struct guest_page       *guest_pages;
> @@ -280,7 +282,6 @@ static inline phys_addr_t __attribute__((always_inline))
>  	return 0;
>  }
>
> -struct virtio_net_device_ops const *notify_ops;
>  struct virtio_net *get_device(int vid);
>
>  int vhost_new_device(void);
> @@ -293,6 +294,8 @@ static inline phys_addr_t __attribute__((always_inline))
>  void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
>  void vhost_enable_dequeue_zero_copy(int vid);
>
> +struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
> +
>  /*
>   * Backend-specific cleanup.
>   *
> diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
> index f7227bf..c101fbc 100644
> --- a/lib/librte_vhost/vhost_user.c
> +++ b/lib/librte_vhost/vhost_user.c
> @@ -131,7 +131,7 @@
>  {
>  	if (dev->flags & VIRTIO_DEV_RUNNING) {
>  		dev->flags &= ~VIRTIO_DEV_RUNNING;
> -		notify_ops->destroy_device(dev->vid);
> +		dev->notify_ops->destroy_device(dev->vid);
>  	}
>
>  	cleanup_device(dev, 0);
> @@ -499,7 +499,7 @@
>  	/* Remove from the data plane. */
>  	if (dev->flags & VIRTIO_DEV_RUNNING) {
>  		dev->flags &= ~VIRTIO_DEV_RUNNING;
> -		notify_ops->destroy_device(dev->vid);
> +		dev->notify_ops->destroy_device(dev->vid);
>  	}
>
>  	if (dev->mem) {
> @@ -680,7 +680,7 @@
>  				"dequeue zero copy is enabled\n");
>  		}
>
> -		if (notify_ops->new_device(dev->vid) == 0)
> +		if (dev->notify_ops->new_device(dev->vid) == 0)
>  			dev->flags |= VIRTIO_DEV_RUNNING;
>  	}
>  }
> @@ -713,7 +713,7 @@
>  	/* We have to stop the queue (virtio) if it is running. */
>  	if (dev->flags & VIRTIO_DEV_RUNNING) {
>  		dev->flags &= ~VIRTIO_DEV_RUNNING;
> -		notify_ops->destroy_device(dev->vid);
> +		dev->notify_ops->destroy_device(dev->vid);
>  	}
>
>  	/* Here we are safe to get the last used index */
> @@ -753,8 +753,8 @@
>  		"set queue enable: %d to qp idx: %d\n",
>  		enable, state->index);
>
> -	if (notify_ops->vring_state_changed)
> -		notify_ops->vring_state_changed(dev->vid, state->index, enable);
> +	if (dev->notify_ops->vring_state_changed)
> +		dev->notify_ops->vring_state_changed(dev->vid, state->index, enable);
>
>  	dev->virtqueue[state->index]->enabled = enable;
>
> @@ -952,6 +952,9 @@
>  	if (dev == NULL)
>  		return -1;
>
> +	if (!dev->notify_ops)
> +		dev->notify_ops = vhost_driver_callback_get(dev->ifname);

Once vhost_driver_callback_get() fixed, notify_ops can be NULL, and it
seems to be dereferenced without being checked later on.

> +
>  	ret = read_vhost_message(fd, &msg);
>  	if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
>  		if (ret < 0)
>

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

* Re: [PATCH 05/17] vhost: export guest memory regions
  2017-03-03  9:51 ` [PATCH 05/17] vhost: export guest memory regions Yuanhan Liu
@ 2017-03-14 11:00   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 11:00 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Some vhost-user driver may need this info to setup its own page tables
> for GPA (guest physical addr) to HPA (host physical addr) translation.
> SPDK (Storage Performance Development Kit) is one example.
>
> Besides, by exporting this memory info, we could also export the
> gpa_to_vva() as an inline function, which helps for performance.
> Otherwise, it has to be referenced indirectly by a "vid".
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 24 ++++++++++++++++++++++++
>  lib/librte_vhost/vhost.c               | 23 +++++++++++++++++++++++
>  lib/librte_vhost/vhost.h               | 28 ++--------------------------
>  lib/librte_vhost/vhost_user.c          | 12 ++++++------
>  5 files changed, 56 insertions(+), 32 deletions(-)
>
> diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
> index ee72d5f..b890da6 100644
> --- a/lib/librte_vhost/rte_vhost_version.map
> +++ b/lib/librte_vhost/rte_vhost_version.map
> @@ -35,5 +35,6 @@ DPDK_17.05 {
>  	rte_vhost_driver_enable_features;
>  	rte_vhost_driver_get_features;
>  	rte_vhost_driver_set_features;
> +	rte_vhost_get_vhost_memory;
>
>  } DPDK_16.07;
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index 3bfd0b7..eddf0f4 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -59,6 +59,28 @@
>  enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
>
>  /**
> + * Information relating to memory regions including offsets to
> + * addresses in QEMUs memory file.
> + */
> +struct rte_vhost_mem_region {
> +	uint64_t guest_phys_addr;
> +	uint64_t guest_user_addr;
> +	uint64_t host_user_addr;
> +	uint64_t size;
> +	void	 *mmap_addr;
> +	uint64_t mmap_size;
> +	int fd;
> +};
> +
> +/**
> + * Memory structure includes region and mapping information.
> + */
> +struct rte_vhost_memory {
> +	uint32_t nregions;
> +	struct rte_vhost_mem_region regions[0];
> +};
> +
> +/**
>   * Device and vring operations.
>   */
>  struct virtio_net_device_ops {
> @@ -187,4 +209,6 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
>  uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
>  	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
>
> +int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
> +
>  #endif /* _VIRTIO_NET_H_ */
> diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
> index 0088f87..eee229a 100644
> --- a/lib/librte_vhost/vhost.c
> +++ b/lib/librte_vhost/vhost.c
> @@ -340,6 +340,29 @@ struct virtio_net *
>  	return 0;
>  }
>
> +int
> +rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem)
> +{
> +	struct virtio_net *dev;
> +	struct rte_vhost_memory *m;
> +	size_t size;
> +
> +	dev = get_device(vid);
> +	if (!dev)
> +		return -1;
> +
> +	size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
> +	m = malloc(size);
> +	if (!m)
> +		return -1;
> +
> +	m->nregions = dev->mem->nregions;
> +	memcpy(m->regions, dev->mem->regions, size);
> +	*mem = m;
> +
> +	return 0;
> +}
> +

Might worth to be documented, as API.
Other than that:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 06/17] vhost: introduce API to fetch negotiated features
  2017-03-03  9:51 ` [PATCH 06/17] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-03-14 11:02   ` Maxime Coquelin
  2017-03-16  7:35     ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 11:02 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      |  1 +
>  lib/librte_vhost/vhost.c               | 12 ++++++++++++
>  3 files changed, 14 insertions(+)
>
> diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
> index b890da6..85a2796 100644
> --- a/lib/librte_vhost/rte_vhost_version.map
> +++ b/lib/librte_vhost/rte_vhost_version.map
> @@ -35,6 +35,7 @@ DPDK_17.05 {
>  	rte_vhost_driver_enable_features;
>  	rte_vhost_driver_get_features;
>  	rte_vhost_driver_set_features;
> +	rte_vhost_get_negotiated_features
>  	rte_vhost_get_vhost_memory;
>
>  } DPDK_16.07;
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index eddf0f4..e7b1599 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -210,5 +210,6 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
>  	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
>
>  int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
> +uint64_t rte_vhost_get_negotiated_features(int vid);
>
>  #endif /* _VIRTIO_NET_H_ */
> diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
> index eee229a..8046aef 100644
> --- a/lib/librte_vhost/vhost.c
> +++ b/lib/librte_vhost/vhost.c
> @@ -340,6 +340,18 @@ struct virtio_net *
>  	return 0;
>  }
>
> +uint64_t
> +rte_vhost_get_negotiated_features(int vid)
> +{
> +	struct virtio_net *dev;
> +
> +	dev = get_device(vid);
> +	if (!dev)
> +		return -1;
> +
> +	return dev->features;
> +}
Are we sure the negotiation is done when we can get the device?

Maxime

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

* Re: [PATCH 07/17] vhost: export vhost vring info
  2017-03-03  9:51 ` [PATCH 07/17] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-14 12:11   ` Maxime Coquelin
  2017-03-16  7:24     ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:11 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 13 +++++++++++++
>  lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.h               |  2 ++
>  4 files changed, 46 insertions(+)
>
> diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
> index 85a2796..efde936 100644
> --- a/lib/librte_vhost/rte_vhost_version.map
> +++ b/lib/librte_vhost/rte_vhost_version.map
> @@ -37,5 +37,6 @@ DPDK_17.05 {
>  	rte_vhost_driver_set_features;
>  	rte_vhost_get_negotiated_features
>  	rte_vhost_get_vhost_memory;
> +	rte_vhost_get_vhost_vring;
>
>  } DPDK_16.07;
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index e7b1599..80209ad 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -80,6 +80,17 @@ struct rte_vhost_memory {
>  	struct rte_vhost_mem_region regions[0];
>  };
>
> +struct rte_vhost_vring {
> +	struct vring_desc	*desc;
> +	struct vring_avail	*avail;
> +	struct vring_used	*used;
> +	uint64_t		log_guest_addr;
> +
> +	int			callfd;
> +	int			kickfd;
> +	uint16_t		size;
> +};
> +
>  /**
>   * Device and vring operations.
>   */
> @@ -211,5 +222,7 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
>
>  int rte_vhost_get_vhost_memory(int vid, struct rte_vhost_memory **mem);
>  uint64_t rte_vhost_get_negotiated_features(int vid);
> +int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
> +			      struct rte_vhost_vring *vring);
>
>  #endif /* _VIRTIO_NET_H_ */
> diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
> index 8046aef..b175f0e 100644
> --- a/lib/librte_vhost/vhost.c
> +++ b/lib/librte_vhost/vhost.c
> @@ -375,6 +375,36 @@ struct virtio_net *
>  	return 0;
>  }
>
> +int
> +rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
> +			  struct rte_vhost_vring *vring)
> +{
> +	struct virtio_net *dev;
> +	struct vhost_virtqueue *vq;
> +
> +	dev = get_device(vid);
> +	if (!dev)
> +		return -1;
> +
> +	if (vring_idx > VHOST_MAX_VRING)
Shouldn't be ">=" ?

> +		return -1;
> +
> +	vq = dev->virtqueue[vring_idx];
> +	if (!vq)
> +		return -1;
> +
> +	vring->desc  = vq->desc;
> +	vring->avail = vq->avail;
> +	vring->used  = vq->used;
> +	vring->log_guest_addr  = vq->log_guest_addr;
> +
> +	vring->callfd  = vq->callfd;
> +	vring->kickfd  = vq->kickfd;
> +	vring->size    = vq->size;
> +
> +	return 0;
> +}
> +
>  uint16_t
>  rte_vhost_avail_entries(int vid, uint16_t queue_id)
>  {
> diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
> index ed7b2c9..b0ef0cc 100644
> --- a/lib/librte_vhost/vhost.h
> +++ b/lib/librte_vhost/vhost.h
> @@ -138,6 +138,8 @@ struct vhost_virtqueue {
>  #ifndef VIRTIO_NET_F_MQ
>   #define VIRTIO_NET_F_MQ		22
>  #endif
> +
> +#define VHOST_MAX_VRING			0x100
Looking at the code, I'm not clear where this limitation comes from.
It seems that it can be up to 0x10000, no?

struct virtio_net {
...
	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];

with:
#ifdef VIRTIO_NET_F_MQ
  #define VHOST_MAX_QUEUE_PAIRS	VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX
  #define VHOST_SUPPORTS_MQ	(1ULL << VIRTIO_NET_F_MQ)
#else
  #define VHOST_MAX_QUEUE_PAIRS	1
  #define VHOST_SUPPORTS_MQ	0
#endif

and:
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000


Regards,
Maxime

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

* Re: [PATCH 08/17] vhost: export API to translate gpa to vva
  2017-03-03  9:51 ` [PATCH 08/17] vhost: export API to translate gpa to vva Yuanhan Liu
@ 2017-03-14 12:24   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:24 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 21 +++++++++++++++++++++
>  lib/librte_vhost/vhost.h               | 19 -------------------
>  lib/librte_vhost/virtio_net.c          | 23 +++++++++++++----------
>  4 files changed, 35 insertions(+), 29 deletions(-)
>

Same remark as previous patches, the API should be documented.
Other than that:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 09/17] vhost: turn queue pair to vring
  2017-03-03  9:51 ` [PATCH 09/17] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-14 12:31   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:31 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> The queue pair is very virtio-net specific, other devices don't have
> such concept. To make it generic, we should log the number of vrings
> instead of the number of queue pairs.
>
> This patch just does a simple convert, a later patch would export the
> number of vrings to applications.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/vhost.c      | 74 ++++++++++++++-----------------------------
>  lib/librte_vhost/vhost.h      |  4 +--
>  lib/librte_vhost/vhost_user.c | 28 +++++-----------
>  lib/librte_vhost/virtio_net.c | 10 +++---
>  4 files changed, 38 insertions(+), 78 deletions(-)
>

Nice. Making it generic simplifies the net specific code.
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 10/17] vhost: export the number of vrings
  2017-03-03  9:51 ` [PATCH 10/17] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-14 12:33   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:33 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> We used to use rte_vhost_get_queue_num() for telling how many vrings.
> However, the return value is the number of "queue pairs", which is
> very virtio-net specific. To make it generic, we should return the
> number of vrings instead, and let the driver do the proper translation.
> Say, virtio-net driver could turn it to the number of queue pairs by
> dividing 2.
>
> Meanwhile, mark rte_vhost_get_queue_num as deprecated.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  drivers/net/vhost/rte_eth_vhost.c      |  2 +-
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 17 +++++++++++++++++
>  lib/librte_vhost/vhost.c               | 11 +++++++++++
>  4 files changed, 30 insertions(+), 1 deletion(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 11/17] vhost: move the device ready check at proper place
  2017-03-03  9:51 ` [PATCH 11/17] vhost: move the device ready check at proper place Yuanhan Liu
@ 2017-03-14 12:37   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:37 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Currently, we check vq->desc, vq->kickfd and vq->callfd to know whether
> a virtio device is ready or not. However, we only do it when handling
> SET_VRING_KICK message, which could be wrong if a vhost-user frontend
> send SET_VRING_KICK first and SET_VRING_CALL later.
>
> To work for all possible vhost-user frontend implementations, we could
> move the ready check at the end of vhost-user message handler.
>
> Meanwhile, since we do the check more often than before, the "virtio
> not ready" message is dropped, to not flood the screen.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/vhost_user.c | 32 ++++++++++++++------------------
>  1 file changed, 14 insertions(+), 18 deletions(-)

Makes sense:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 12/17] vhost: drop the Rx and Tx queue macro
  2017-03-03  9:51 ` [PATCH 12/17] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-03-14 12:42   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:42 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> They are virti-net specific and should be defined inside the virtio-net
s/virti-net/virtio-net/

> driver.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  drivers/net/vhost/rte_eth_vhost.c | 2 ++
>  examples/tep_termination/main.h   | 2 ++
>  examples/vhost/main.h             | 2 ++
>  lib/librte_vhost/rte_virtio_net.h | 3 ---
>  4 files changed, 6 insertions(+), 3 deletions(-)

With the commit msg fixed:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 13/17] vhost: do not include net specific headers
  2017-03-03  9:51 ` [PATCH 13/17] vhost: do not include net specific headers Yuanhan Liu
@ 2017-03-14 12:46   ` Maxime Coquelin
  2017-03-20  7:32   ` Liu, Changpeng
  1 sibling, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:46 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Include it internally, at vhost.h.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  examples/vhost/main.h             | 2 ++
>  lib/librte_vhost/rte_virtio_net.h | 4 ----
>  lib/librte_vhost/vhost.h          | 4 ++++
>  3 files changed, 6 insertions(+), 4 deletions(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

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

* Re: [PATCH 14/17] vhost: rename device ops struct
  2017-03-03  9:51 ` [PATCH 14/17] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-14 12:48   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:48 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> rename "virtio_net_device_ops" to "vhost_device_ops", to not let it
> be virtio-net specific.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  drivers/net/vhost/rte_eth_vhost.c | 2 +-
>  examples/tep_termination/main.c   | 4 ++--
>  examples/vhost/main.c             | 4 ++--
>  lib/librte_vhost/Makefile         | 2 +-
>  lib/librte_vhost/rte_virtio_net.h | 4 ++--
>  lib/librte_vhost/socket.c         | 6 +++---
>  lib/librte_vhost/vhost.h          | 4 ++--
>  7 files changed, 13 insertions(+), 13 deletions(-)
>

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 15/17] vhost: rename virtio-net to vhost
  2017-03-03  9:51 ` [PATCH 15/17] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-03-14 12:50   ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:50 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Rename "virtio-net" to "vhost" in the API comments.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_virtio_net.h | 14 +++++++-------
>  1 file changed, 7 insertions(+), 7 deletions(-)
>

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Thanks,
Maxime

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

* Re: [PATCH 16/17] vhost: rename header file
  2017-03-03  9:51 ` [PATCH 16/17] vhost: rename header file Yuanhan Liu
@ 2017-03-14 12:59   ` Maxime Coquelin
  2017-03-20  5:35     ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-14 12:59 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
> net specific.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  doc/guides/rel_notes/deprecation.rst   |   9 --
>  drivers/net/vhost/rte_eth_vhost.c      |   2 +-
>  drivers/net/vhost/rte_eth_vhost.h      |   2 +-
>  examples/tep_termination/main.c        |   2 +-
>  examples/tep_termination/vxlan_setup.c |   2 +-
>  examples/vhost/main.c                  |   2 +-
>  lib/librte_vhost/Makefile              |   2 +-
>  lib/librte_vhost/rte_vhost.h           | 259 +++++++++++++++++++++++++++++++++
>  lib/librte_vhost/rte_virtio_net.h      | 259 ---------------------------------
Did you perform the rename using git mv?

>  lib/librte_vhost/vhost.c               |   2 +-
>  lib/librte_vhost/vhost.h               |   2 +-
>  lib/librte_vhost/vhost_user.h          |   2 +-
>  lib/librte_vhost/virtio_net.c          |   2 +-
>  13 files changed, 269 insertions(+), 278 deletions(-)
>  create mode 100644 lib/librte_vhost/rte_vhost.h
>  delete mode 100644 lib/librte_vhost/rte_virtio_net.h

Other than that, the change looks good to me:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-14  9:53     ` Maxime Coquelin
@ 2017-03-16  7:08       ` Yuanhan Liu
  2017-03-16  9:18         ` Maxime Coquelin
  0 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-16  7:08 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 10:53:23AM +0100, Maxime Coquelin wrote:
> 
> 
> On 03/14/2017 10:46 AM, Maxime Coquelin wrote:
> >
> >
> >On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> >>Introduce few APIs to set/get/enable/disable driver features.
> >>
> >>Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> >>---
> >> lib/librte_vhost/rte_vhost_version.map | 10 ++++
> >> lib/librte_vhost/rte_virtio_net.h      |  9 ++++
> >> lib/librte_vhost/socket.c              | 90
> >>++++++++++++++++++++++++++++++++++
> >> 3 files changed, 109 insertions(+)
> >
> >Nice!
> >Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> >
> >I wonder whether we could protect from setting/enabling/disabling
> >features once negotiation is done?

Those APIs won't be able to change the negotiated features. They are
just some interfaces before the vhost-user connection is established.

Ideally, we could/should get rid of the enabling/disabling functions:
let the vhost-user driver to handle the features directly (say, for
vhost-user pmd, we could use vdev options to disable/enable few specific
features). Once that is done, use the rte_vhost_driver_set_features()
set the features once.

The reason I introduced the enable/disable_features() is to keep the
compatability with the builtin vhost-user net driver (virtio_net.c).
If there is a plan to move it into vhost-pmd, they won't be needed.
And I don't think that will happen soon.

> Oh, I forgot one comment on this patch.
> Since these new functions are part to the API, shouldn't them be
> documented?

Yes, indeed, it's also noted in my cover letter.

	--yliu

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

* Re: [PATCH 07/17] vhost: export vhost vring info
  2017-03-14 12:11   ` Maxime Coquelin
@ 2017-03-16  7:24     ` Yuanhan Liu
  2017-03-16  9:20       ` Maxime Coquelin
  0 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-16  7:24 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 01:11:24PM +0100, Maxime Coquelin wrote:
> >+int
> >+rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
> >+			  struct rte_vhost_vring *vring)
> >+{
> >+	struct virtio_net *dev;
> >+	struct vhost_virtqueue *vq;
> >+
> >+	dev = get_device(vid);
> >+	if (!dev)
> >+		return -1;
> >+
> >+	if (vring_idx > VHOST_MAX_VRING)
> Shouldn't be ">=" ?

Nice catch!

> >+#define VHOST_MAX_VRING			0x100
> Looking at the code, I'm not clear where this limitation comes from.
> It seems that it can be up to 0x10000, no?

It comes from the vhost-user spec:

	--yliu

---
 * VHOST_USER_SET_VRING_KICK

      Id: 12
      Equivalent ioctl: VHOST_SET_VRING_KICK
      Master payload: u64

      Set the event file descriptor for adding buffers to the vring. It
      is passed in the ancillary data.
      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. This signals that polling should be used
      instead of waiting for a kick.
> 
> struct virtio_net {
> ...
> 	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];
> 
> with:
> #ifdef VIRTIO_NET_F_MQ
>  #define VHOST_MAX_QUEUE_PAIRS	VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX
>  #define VHOST_SUPPORTS_MQ	(1ULL << VIRTIO_NET_F_MQ)
> #else
>  #define VHOST_MAX_QUEUE_PAIRS	1
>  #define VHOST_SUPPORTS_MQ	0
> #endif
> 
> and:
> #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX        0x8000
> 
> 
> Regards,
> Maxime

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

* Re: [PATCH 06/17] vhost: introduce API to fetch negotiated features
  2017-03-14 11:02   ` Maxime Coquelin
@ 2017-03-16  7:35     ` Yuanhan Liu
  2017-03-16  9:22       ` Maxime Coquelin
  0 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-16  7:35 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 12:02:59PM +0100, Maxime Coquelin wrote:
> >+uint64_t
> >+rte_vhost_get_negotiated_features(int vid)
> >+{
> >+	struct virtio_net *dev;
> >+
> >+	dev = get_device(vid);
> >+	if (!dev)
> >+		return -1;
> >+
> >+	return dev->features;
> >+}
> Are we sure the negotiation is done when we can get the device?

Yes. However, one thing worth noting is that the features may change
after the new_device() callback. Notablely, when live migration starts
/ends, the VHOST_F_LOG_ALL will be set/cleared, respectively.

>From that point of view, we need a new callback, something like
features_changed(), or live_migration_starts()? Or a better name?

	--yliu

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

* Re: [PATCH 03/17] vhost: use new APIs to handle features
  2017-03-14 10:43   ` Maxime Coquelin
@ 2017-03-16  7:43     ` Yuanhan Liu
  2017-03-16  9:39       ` Maxime Coquelin
  0 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-16  7:43 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 11:43:44AM +0100, Maxime Coquelin wrote:
> >diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
> >index 8433a54..f7227bf 100644
> >--- a/lib/librte_vhost/vhost_user.c
> >+++ b/lib/librte_vhost/vhost_user.c
> >@@ -143,9 +143,9 @@
> >  * The features that we support are requested.
> >  */
> > static uint64_t
> >-vhost_user_get_features(void)
> >+vhost_user_get_features(struct virtio_net *dev)
> > {
> >-	return VHOST_FEATURES;
> >+	return rte_vhost_driver_get_features(dev->ifname);
> > }
> >
> > /*
> >@@ -154,7 +154,7 @@
> > static int
> > vhost_user_set_features(struct virtio_net *dev, uint64_t features)
> > {
> >-	if (features & ~VHOST_FEATURES)
> >+	if (features & ~rte_vhost_driver_get_features(dev->ifname))
> 
> rte_vhost_driver_get_features() returns -1 if the socket is not found.
> It would result in accepting any feature trying to be set.

If we have gone here, I think rte_vhost_driver_get_features() should not
return -1. The only exception is user unregistered such socket during
the negotiation?

	--yliu

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

* Re: [PATCH 04/17] vhost: make notify ops per vhost driver
  2017-03-14 10:55   ` Maxime Coquelin
@ 2017-03-16  7:50     ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-16  7:50 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 11:55:20AM +0100, Maxime Coquelin wrote:
> >diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
> >index 8c45128..03c0fbe 100644
> >--- a/examples/tep_termination/main.c
> >+++ b/examples/tep_termination/main.c
> >@@ -1258,7 +1258,8 @@ static inline void __attribute__((always_inline))
> > 	rte_vhost_driver_disable_features(dev_basename,
> > 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
> >
> >-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
> >+	rte_vhost_driver_callback_register(dev_basename,
> >+		&virtio_net_device_ops);
> 
> Return should be checked here, as this function can now return -1.

Right.

> >+struct virtio_net_device_ops const *
> >+vhost_driver_callback_get(const char *path)
> >+{
> >+	struct vhost_user_socket *vsocket;
> >+
> >+	pthread_mutex_lock(&vhost_user.mutex);
> >+	vsocket = find_vhost_user_socket(path);
> >+	pthread_mutex_unlock(&vhost_user.mutex);
> >+
> >+	return vsocket->notify_ops;
> 
> There should be a check against vsocket to avoid NULL pointer
> dereferencing.

Yes.

> >@@ -952,6 +952,9 @@
> > 	if (dev == NULL)
> > 		return -1;
> >
> >+	if (!dev->notify_ops)
> >+		dev->notify_ops = vhost_driver_callback_get(dev->ifname);
> 
> Once vhost_driver_callback_get() fixed, notify_ops can be NULL, and it
> seems to be dereferenced without being checked later on.

Yes.

	--yliu

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

* Re: [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-16  7:08       ` Yuanhan Liu
@ 2017-03-16  9:18         ` Maxime Coquelin
  2017-03-17  5:50           ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-16  9:18 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Harris James R, Liu Changpeng



On 03/16/2017 08:08 AM, Yuanhan Liu wrote:
> On Tue, Mar 14, 2017 at 10:53:23AM +0100, Maxime Coquelin wrote:
>>
>>
>> On 03/14/2017 10:46 AM, Maxime Coquelin wrote:
>>>
>>>
>>> On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
>>>> Introduce few APIs to set/get/enable/disable driver features.
>>>>
>>>> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
>>>> ---
>>>> lib/librte_vhost/rte_vhost_version.map | 10 ++++
>>>> lib/librte_vhost/rte_virtio_net.h      |  9 ++++
>>>> lib/librte_vhost/socket.c              | 90
>>>> ++++++++++++++++++++++++++++++++++
>>>> 3 files changed, 109 insertions(+)
>>>
>>> Nice!
>>> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
>>>
>>> I wonder whether we could protect from setting/enabling/disabling
>>> features once negotiation is done?
>
> Those APIs won't be able to change the negotiated features. They are
> just some interfaces before the vhost-user connection is established.

Right.
I meant it could return an error is the connection is already
established. Else, the caller might think the feature has been
successfully enabled/disabled, whereas it is not the case.
But this is maybe over-engineering to handle this case.

> Ideally, we could/should get rid of the enabling/disabling functions:
> let the vhost-user driver to handle the features directly (say, for
> vhost-user pmd, we could use vdev options to disable/enable few specific
> features). Once that is done, use the rte_vhost_driver_set_features()
> set the features once.

Ok, but what about vhost lib users and TSO (I'm thinking of OVS).

> The reason I introduced the enable/disable_features() is to keep the
> compatability with the builtin vhost-user net driver (virtio_net.c).
> If there is a plan to move it into vhost-pmd, they won't be needed.
> And I don't think that will happen soon.

I agree with you that would be ideal, but unlikely to happen soon.

>> Oh, I forgot one comment on this patch.
>> Since these new functions are part to the API, shouldn't them be
>> documented?
>
> Yes, indeed, it's also noted in my cover letter.

Oops, I missed that!

Thanks,
Maxime
> 	--yliu
>

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

* Re: [PATCH 07/17] vhost: export vhost vring info
  2017-03-16  7:24     ` Yuanhan Liu
@ 2017-03-16  9:20       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-16  9:20 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Harris James R, Liu Changpeng



On 03/16/2017 08:24 AM, Yuanhan Liu wrote:
> On Tue, Mar 14, 2017 at 01:11:24PM +0100, Maxime Coquelin wrote:
>>> +int
>>> +rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
>>> +			  struct rte_vhost_vring *vring)
>>> +{
>>> +	struct virtio_net *dev;
>>> +	struct vhost_virtqueue *vq;
>>> +
>>> +	dev = get_device(vid);
>>> +	if (!dev)
>>> +		return -1;
>>> +
>>> +	if (vring_idx > VHOST_MAX_VRING)
>> Shouldn't be ">=" ?
>
> Nice catch!
>
>>> +#define VHOST_MAX_VRING			0x100
>> Looking at the code, I'm not clear where this limitation comes from.
>> It seems that it can be up to 0x10000, no?
>
> It comes from the vhost-user spec:
>
> 	--yliu
>
> ---
>  * VHOST_USER_SET_VRING_KICK
>
>       Id: 12
>       Equivalent ioctl: VHOST_SET_VRING_KICK
>       Master payload: u64
>
>       Set the event file descriptor for adding buffers to the vring. It
>       is passed in the ancillary data.
>       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. This signals that polling should be used
>       instead of waiting for a kick.

Thanks for the pointer.

With the vring_idx check fixed you can add my:
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Cheers,
Maxime

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

* Re: [PATCH 06/17] vhost: introduce API to fetch negotiated features
  2017-03-16  7:35     ` Yuanhan Liu
@ 2017-03-16  9:22       ` Maxime Coquelin
  2017-03-17  5:49         ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-16  9:22 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Harris James R, Liu Changpeng



On 03/16/2017 08:35 AM, Yuanhan Liu wrote:
> On Tue, Mar 14, 2017 at 12:02:59PM +0100, Maxime Coquelin wrote:
>>> +uint64_t
>>> +rte_vhost_get_negotiated_features(int vid)
>>> +{
>>> +	struct virtio_net *dev;
>>> +
>>> +	dev = get_device(vid);
>>> +	if (!dev)
>>> +		return -1;
>>> +
>>> +	return dev->features;
>>> +}
>> Are we sure the negotiation is done when we can get the device?
>
> Yes. However, one thing worth noting is that the features may change
> after the new_device() callback. Notablely, when live migration starts
> /ends, the VHOST_F_LOG_ALL will be set/cleared, respectively.

Good point.

> From that point of view, we need a new callback, something like
> features_changed(), or live_migration_starts()? Or a better name?

I would name it features_changed() to be future-proof (even if I don't
foresee other cases than live migration right now).

Thanks,
Maxime

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

* Re: [PATCH 03/17] vhost: use new APIs to handle features
  2017-03-16  7:43     ` Yuanhan Liu
@ 2017-03-16  9:39       ` Maxime Coquelin
  2017-03-17  5:48         ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-16  9:39 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Harris James R, Liu Changpeng



On 03/16/2017 08:43 AM, Yuanhan Liu wrote:
> On Tue, Mar 14, 2017 at 11:43:44AM +0100, Maxime Coquelin wrote:
>>> diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
>>> index 8433a54..f7227bf 100644
>>> --- a/lib/librte_vhost/vhost_user.c
>>> +++ b/lib/librte_vhost/vhost_user.c
>>> @@ -143,9 +143,9 @@
>>>  * The features that we support are requested.
>>>  */
>>> static uint64_t
>>> -vhost_user_get_features(void)
>>> +vhost_user_get_features(struct virtio_net *dev)
>>> {
>>> -	return VHOST_FEATURES;
>>> +	return rte_vhost_driver_get_features(dev->ifname);
>>> }
>>>
>>> /*
>>> @@ -154,7 +154,7 @@
>>> static int
>>> vhost_user_set_features(struct virtio_net *dev, uint64_t features)
>>> {
>>> -	if (features & ~VHOST_FEATURES)
>>> +	if (features & ~rte_vhost_driver_get_features(dev->ifname))
>>
>> rte_vhost_driver_get_features() returns -1 if the socket is not found.
>> It would result in accepting any feature trying to be set.
>
> If we have gone here, I think rte_vhost_driver_get_features() should not
> return -1. The only exception is user unregistered such socket during
> the negotiation?

Maybe this could never happen.
I just noticed that rte_vhost_driver_get_features() can fail, and in
that case, we wouldn't see it and the behavior could make hard the
cause to be hard to spot.

As this is not in the hot code path, my view is that checking its return 
and print an error message does not hurt.

Or maybe we could directly do the error prints into
rte_vhost_driver_*_features() functions if the socket name is not found?

Cheers,
Maxime

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

* Re: [PATCH 03/17] vhost: use new APIs to handle features
  2017-03-16  9:39       ` Maxime Coquelin
@ 2017-03-17  5:48         ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-17  5:48 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Thu, Mar 16, 2017 at 10:39:00AM +0100, Maxime Coquelin wrote:
> 
> 
> On 03/16/2017 08:43 AM, Yuanhan Liu wrote:
> >On Tue, Mar 14, 2017 at 11:43:44AM +0100, Maxime Coquelin wrote:
> >>>diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
> >>>index 8433a54..f7227bf 100644
> >>>--- a/lib/librte_vhost/vhost_user.c
> >>>+++ b/lib/librte_vhost/vhost_user.c
> >>>@@ -143,9 +143,9 @@
> >>> * The features that we support are requested.
> >>> */
> >>>static uint64_t
> >>>-vhost_user_get_features(void)
> >>>+vhost_user_get_features(struct virtio_net *dev)
> >>>{
> >>>-	return VHOST_FEATURES;
> >>>+	return rte_vhost_driver_get_features(dev->ifname);
> >>>}
> >>>
> >>>/*
> >>>@@ -154,7 +154,7 @@
> >>>static int
> >>>vhost_user_set_features(struct virtio_net *dev, uint64_t features)
> >>>{
> >>>-	if (features & ~VHOST_FEATURES)
> >>>+	if (features & ~rte_vhost_driver_get_features(dev->ifname))
> >>
> >>rte_vhost_driver_get_features() returns -1 if the socket is not found.
> >>It would result in accepting any feature trying to be set.
> >
> >If we have gone here, I think rte_vhost_driver_get_features() should not
> >return -1. The only exception is user unregistered such socket during
> >the negotiation?
> 
> Maybe this could never happen.
> I just noticed that rte_vhost_driver_get_features() can fail, and in
> that case, we wouldn't see it and the behavior could make hard the
> cause to be hard to spot.
> 
> As this is not in the hot code path, my view is that checking its return and
> print an error message does not hurt.
> 
> Or maybe we could directly do the error prints into
> rte_vhost_driver_*_features() functions if the socket name is not found?

Yes, I think we could do that. Thanks!

	--yliu

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

* Re: [PATCH 06/17] vhost: introduce API to fetch negotiated features
  2017-03-16  9:22       ` Maxime Coquelin
@ 2017-03-17  5:49         ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-17  5:49 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Thu, Mar 16, 2017 at 10:22:27AM +0100, Maxime Coquelin wrote:
> 
> 
> On 03/16/2017 08:35 AM, Yuanhan Liu wrote:
> >On Tue, Mar 14, 2017 at 12:02:59PM +0100, Maxime Coquelin wrote:
> >>>+uint64_t
> >>>+rte_vhost_get_negotiated_features(int vid)
> >>>+{
> >>>+	struct virtio_net *dev;
> >>>+
> >>>+	dev = get_device(vid);
> >>>+	if (!dev)
> >>>+		return -1;
> >>>+
> >>>+	return dev->features;
> >>>+}
> >>Are we sure the negotiation is done when we can get the device?
> >
> >Yes. However, one thing worth noting is that the features may change
> >after the new_device() callback. Notablely, when live migration starts
> >/ends, the VHOST_F_LOG_ALL will be set/cleared, respectively.
> 
> Good point.
> 
> >From that point of view, we need a new callback, something like
> >features_changed(), or live_migration_starts()? Or a better name?
> 
> I would name it features_changed() to be future-proof (even if I don't
> foresee other cases than live migration right now).

Right, it will be "features_changed()" then.

	--yliu

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

* Re: [PATCH 01/17] vhost: introduce driver features related APIs
  2017-03-16  9:18         ` Maxime Coquelin
@ 2017-03-17  5:50           ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-17  5:50 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Thu, Mar 16, 2017 at 10:18:21AM +0100, Maxime Coquelin wrote:
> 
> 
> On 03/16/2017 08:08 AM, Yuanhan Liu wrote:
> >On Tue, Mar 14, 2017 at 10:53:23AM +0100, Maxime Coquelin wrote:
> >>
> >>
> >>On 03/14/2017 10:46 AM, Maxime Coquelin wrote:
> >>>
> >>>
> >>>On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> >>>>Introduce few APIs to set/get/enable/disable driver features.
> >>>>
> >>>>Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> >>>>---
> >>>>lib/librte_vhost/rte_vhost_version.map | 10 ++++
> >>>>lib/librte_vhost/rte_virtio_net.h      |  9 ++++
> >>>>lib/librte_vhost/socket.c              | 90
> >>>>++++++++++++++++++++++++++++++++++
> >>>>3 files changed, 109 insertions(+)
> >>>
> >>>Nice!
> >>>Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> >>>
> >>>I wonder whether we could protect from setting/enabling/disabling
> >>>features once negotiation is done?
> >
> >Those APIs won't be able to change the negotiated features. They are
> >just some interfaces before the vhost-user connection is established.
> 
> Right.
> I meant it could return an error is the connection is already
> established. Else, the caller might think the feature has been
> successfully enabled/disabled, whereas it is not the case.
> But this is maybe over-engineering to handle this case.
> 
> >Ideally, we could/should get rid of the enabling/disabling functions:
> >let the vhost-user driver to handle the features directly (say, for
> >vhost-user pmd, we could use vdev options to disable/enable few specific
> >features). Once that is done, use the rte_vhost_driver_set_features()
> >set the features once.
> 
> Ok, but what about vhost lib users and TSO (I'm thinking of OVS).

Yes, that's why I kept them :)

	--yliu
> 
> >The reason I introduced the enable/disable_features() is to keep the
> >compatability with the builtin vhost-user net driver (virtio_net.c).
> >If there is a plan to move it into vhost-pmd, they won't be needed.
> >And I don't think that will happen soon.
> 
> I agree with you that would be ideal, but unlikely to happen soon.
> 
> >>Oh, I forgot one comment on this patch.
> >>Since these new functions are part to the API, shouldn't them be
> >>documented?
> >
> >Yes, indeed, it's also noted in my cover letter.
> 
> Oops, I missed that!
> 
> Thanks,
> Maxime
> >	--yliu
> >

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

* Re: [PATCH 16/17] vhost: rename header file
  2017-03-14 12:59   ` Maxime Coquelin
@ 2017-03-20  5:35     ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-20  5:35 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Tue, Mar 14, 2017 at 01:59:49PM +0100, Maxime Coquelin wrote:
> 
> 
> On 03/03/2017 10:51 AM, Yuanhan Liu wrote:
> >Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
> >net specific.
> >
> >Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> >---
> > doc/guides/rel_notes/deprecation.rst   |   9 --
> > drivers/net/vhost/rte_eth_vhost.c      |   2 +-
> > drivers/net/vhost/rte_eth_vhost.h      |   2 +-
> > examples/tep_termination/main.c        |   2 +-
> > examples/tep_termination/vxlan_setup.c |   2 +-
> > examples/vhost/main.c                  |   2 +-
> > lib/librte_vhost/Makefile              |   2 +-
> > lib/librte_vhost/rte_vhost.h           | 259 +++++++++++++++++++++++++++++++++
> > lib/librte_vhost/rte_virtio_net.h      | 259 ---------------------------------
> Did you perform the rename using git mv?

Yes, and I forgot to add '-M' option while run "git format-patch".

	--yliu
> 
> > lib/librte_vhost/vhost.c               |   2 +-
> > lib/librte_vhost/vhost.h               |   2 +-
> > lib/librte_vhost/vhost_user.h          |   2 +-
> > lib/librte_vhost/virtio_net.c          |   2 +-
> > 13 files changed, 269 insertions(+), 278 deletions(-)
> > create mode 100644 lib/librte_vhost/rte_vhost.h
> > delete mode 100644 lib/librte_vhost/rte_virtio_net.h
> 
> Other than that, the change looks good to me:
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> 
> Thanks,
> Maxime

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

* Re: [PATCH 13/17] vhost: do not include net specific headers
  2017-03-03  9:51 ` [PATCH 13/17] vhost: do not include net specific headers Yuanhan Liu
  2017-03-14 12:46   ` Maxime Coquelin
@ 2017-03-20  7:32   ` Liu, Changpeng
  2017-03-22  6:21     ` Yuanhan Liu
  1 sibling, 1 reply; 135+ messages in thread
From: Liu, Changpeng @ 2017-03-20  7:32 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Maxime Coquelin, Harris, James R



> -----Original Message-----
> From: Yuanhan Liu [mailto:yuanhan.liu@linux.intel.com]
> Sent: Friday, March 3, 2017 5:51 PM
> To: dev@dpdk.org
> Cc: Maxime Coquelin <maxime.coquelin@redhat.com>; Harris, James R
> <james.r.harris@intel.com>; Liu, Changpeng <changpeng.liu@intel.com>; Yuanhan
> Liu <yuanhan.liu@linux.intel.com>
> Subject: [PATCH 13/17] vhost: do not include net specific headers
> 
> Include it internally, at vhost.h.
> 
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  examples/vhost/main.h             | 2 ++
>  lib/librte_vhost/rte_virtio_net.h | 4 ----
>  lib/librte_vhost/vhost.h          | 4 ++++
>  3 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/examples/vhost/main.h b/examples/vhost/main.h
> index 7a3d251..ddcd858 100644
> --- a/examples/vhost/main.h
> +++ b/examples/vhost/main.h
> @@ -36,6 +36,8 @@
> 
>  #include <sys/queue.h>
> 
> +#include <rte_ether.h>
> +
>  /* Macros for printing using RTE_LOG */
>  #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
>  #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index fa98d29..e19ebad 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -42,14 +42,10 @@
>  #include <stdint.h>
>  #include <linux/vhost.h>
>  #include <linux/virtio_ring.h>
> -#include <linux/virtio_net.h>
>  #include <sys/eventfd.h>
> -#include <sys/socket.h>
> -#include <linux/if.h>
> 
>  #include <rte_memory.h>
>  #include <rte_mempool.h>
> -#include <rte_ether.h>

One small nits here, remove net specific headers is good idea, since API rte_vhost_dequeue_burst/rte_vhost_enqueue_burst 
has "struct rte_mbuf" declared parameter, user must include <rte_mbuf.h> in their own applications.
Can we add extra line "struct rte_mbuf;" before the rte_vhost_dequeue_burst/rte_vhost_enqueue_burst
APIs to avoid such extra includes?

> 
>  #define RTE_VHOST_USER_CLIENT		(1ULL << 0)
>  #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
> diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
> index 829a45b..5bc0ebe 100644
> --- a/lib/librte_vhost/vhost.h
> +++ b/lib/librte_vhost/vhost.h
> @@ -39,8 +39,12 @@
>  #include <sys/queue.h>
>  #include <unistd.h>
>  #include <linux/vhost.h>
> +#include <linux/virtio_net.h>
> +#include <sys/socket.h>
> +#include <linux/if.h>
> 
>  #include <rte_log.h>
> +#include <rte_ether.h>
> 
>  #include "rte_virtio_net.h"
> 
> --
> 1.9.0

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

* Re: [PATCH 13/17] vhost: do not include net specific headers
  2017-03-20  7:32   ` Liu, Changpeng
@ 2017-03-22  6:21     ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-22  6:21 UTC (permalink / raw)
  To: Liu, Changpeng; +Cc: dev, Maxime Coquelin, Harris, James R

On Mon, Mar 20, 2017 at 07:32:45AM +0000, Liu, Changpeng wrote:
> > diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> > index fa98d29..e19ebad 100644
> > --- a/lib/librte_vhost/rte_virtio_net.h
> > +++ b/lib/librte_vhost/rte_virtio_net.h
> > @@ -42,14 +42,10 @@
> >  #include <stdint.h>
> >  #include <linux/vhost.h>
> >  #include <linux/virtio_ring.h>
> > -#include <linux/virtio_net.h>
> >  #include <sys/eventfd.h>
> > -#include <sys/socket.h>
> > -#include <linux/if.h>
> > 
> >  #include <rte_memory.h>
> >  #include <rte_mempool.h>
> > -#include <rte_ether.h>
> 
> One small nits here, remove net specific headers is good idea, since API rte_vhost_dequeue_burst/rte_vhost_enqueue_burst 
> has "struct rte_mbuf" declared parameter, user must include <rte_mbuf.h> in their own applications.
> Can we add extra line "struct rte_mbuf;" before the rte_vhost_dequeue_burst/rte_vhost_enqueue_burst
> APIs to avoid such extra includes?

Good suggestion, and sure, we can do that.

And I had a plan to add a config option to not build the net driver
when it's given. Thus, it could give us a vhost with minimum dependences,
say no dependence on mbuf, on rte_malloc and etc. 

I was thinking to name it to "CONFIG_RTE_VHOST_MINIMUM", or something
like that. It's likely something I will do in the next release.

	--yliu

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

* [PATCH v2 00/22] vhost: generic vhost API
  2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
                   ` (16 preceding siblings ...)
  2017-03-03  9:51 ` [PATCH 17/17] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
@ 2017-03-23  7:10 ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
                     ` (22 more replies)
  17 siblings, 23 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

This patchset makes DPDK vhost library be generic enough, so that we could
build other vhost-user drivers on top of it. For example, SPDK (Storage
Performance Development Kit) is trying to enable vhost-user SCSI.

The basic idea is, let DPDK vhost be a vhost-user agent. It stores all
the info about the virtio device (i.e. vring address, negotiated features,
etc) and let the specific vhost-user driver to fetch them (by the API
provided by DPDK vhost lib). With those info being provided, the vhost-user
driver then could get/put vring entries, thus, it could exchange data
between the guest and host.

The last patch demonstrates how to use these new APIs to implement a
very simple vhost-user net driver, without any fancy features enabled.


Major API/ABI Changes summary
=============================

- some renames
  * "struct virtio_net_device_ops" ==> "struct vhost_device_ops"
  * "rte_virtio_net.h"  ==> "rte_vhost.h"

- driver related APIs are bond with the socket file
  * rte_vhost_driver_set_features(socket_file, features);
  * rte_vhost_driver_get_features(socket_file, features);
  * rte_vhost_driver_enable_features(socket_file, features)
  * rte_vhost_driver_disable_features(socket_file, features)
  * rte_vhost_driver_callback_register(socket_file, notify_ops);
  * rte_vhost_driver_start(socket_file);
    This function replaces rte_vhost_driver_session_start(). Check patch
    18 for more information.

- new APIs to fetch guest and vring info
  * rte_vhost_get_mem_table(vid, mem);
  * rte_vhost_get_negotiated_features(vid);
  * rte_vhost_get_vhost_vring(vid, vring_idx, vring);

- new exported structures 
  * struct rte_vhost_vring
  * struct rte_vhost_mem_region
  * struct rte_vhost_memory

- a new device ops callback: features_changed().


Change log
==========

v2: - rebase
    - updated release note
    - updated API comments
    - renamed rte_vhost_get_vhost_memory to rte_vhost_get_mem_table

    - added a new device callback: features_changed(), bascially for live
      migration support
    - introduced rte_vhost_driver_start() to start a specific driver
    - misc fixes


Some design choices
===================

While making this patchset, I met quite few design choices and here are
two of them, with the issue and the reason I made such choices provided.
Please let me know if you have any comments (or better ideas).

Export public structures or not
-------------------------------

I made an ABI refactor last time (v16.07): move all the structures
internally and let applications use a "vid" to reference the internal
struct. With that, I hope we could never worry about the annoying ABI
issues.

It works great (and as expected) since then, as far as we only support
virito-net, as far as we can handle all the descs inside vhost lib. It
becomes problematic when a user wants to implement a vhost-user driver
somewhere. For example, it needs do the GPA to VVA translation. Without
any structs exported, some functions like gpa_to_vva() can't be inlined.
Calling it would be costly, especially it's a function we have to invoke
for processing each vring desc.

For that reason, the guest memory regions are exported. With that, the
gpa_to_vva could be inlined.

  
Add helper functions to fetch/update descs or not
-------------------------------------------------

I intended to do it like this way: introduce one function to get @count
of descs from a specific vring and another one to update the used descs.
It's something like
    rte_vhost_vring_get_descs(vid, vring_idx, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vid, vring_idx, count, offset, descs);

With that, vhost-user driver programmer's task would be easier, as he/she
doesn't have to parse the descs any more (such as to handle indirect desc).

But judging that virtio 1.1 is just emerged and it proposes a completely
ring layout, and most importantly, the vring desc structure is also changed,
I'd like to hold the introducation of such two functions. Otherwise, it's
very likely the two will be invalid when virtio 1.1 is out. Though I think
it may could be addressed with a care design, something like making the IOV
generic enough:

	struct rte_vhost_iov {
		uint64_t	gpa;
		uint64_t	vva;
		uint64_t	len;
	};

Instead, I go with the other way: introduce few APIs to export all the vring
infos (vring size, vring addr, callfd, etc), and let the vhost-user driver
read and update the descs. Those info could be passed to vhost-user driver
by introducing one API for each, but for saving few APIs and reducing few
calls for the programmer, I packed few key fields into a new structure, so
that it can be fetched with one call:
        struct rte_vhost_vring {
                struct vring_desc       *desc;
                struct vring_avail      *avail;
                struct vring_used       *used;
                uint64_t                log_guest_addr;
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

When virtio 1.1 comes out, likely a simple change like following would
just work:
        struct rte_vhost_vring {
		union {
			struct {
                		struct vring_desc       *desc;
                		struct vring_avail      *avail;
                		struct vring_used       *used;
                		uint64_t                log_guest_addr;
			};
			struct desc	*desc_1_1;	/* vring addr for virtio 1.1 */
		};
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

AFAIK, it's not an ABI breakage. Even if it does, we could introduce a new
API to get the virtio 1.1 ring address.

Those fields are the minimum set I got for a specific vring, with the mind
it would bring the minimum chance to break ABI for future extension. If we
need more info, we could introduce a new API.

OTOH, for getting the best performance, the two functions also have to be
inlined ("vid + vring_idx" combo is replaced with "vring"):
    rte_vhost_vring_get_descs(vring, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vring, count, offset, descs);

That said, one way or another, we have to export rte_vhost_vring struct.
For this reason, I didn't rush into introducing the two APIs.

	--yliu

---
Yuanhan Liu (22):
  vhost: introduce driver features related APIs
  net/vhost: remove feature related APIs
  vhost: use new APIs to handle features
  vhost: make notify ops per vhost driver
  vhost: export guest memory regions
  vhost: introduce API to fetch negotiated features
  vhost: export vhost vring info
  vhost: export API to translate gpa to vva
  vhost: turn queue pair to vring
  vhost: export the number of vrings
  vhost: move the device ready check at proper place
  vhost: drop the Rx and Tx queue macro
  vhost: do not include net specific headers
  vhost: rename device ops struct
  vhost: rename virtio-net to vhost
  vhost: add features changed callback
  vhost: export APIs for live migration support
  vhost: introduce API to start a specific driver
  vhost: rename header file
  vhost: workaround the build dependency on mbuf header
  vhost: do not destroy device on repeat mem table message
  examples/vhost: demonstrate the new generic vhost APIs

 doc/guides/prog_guide/vhost_lib.rst         |  42 +--
 doc/guides/rel_notes/deprecation.rst        |   9 -
 doc/guides/rel_notes/release_17_05.rst      |  40 +++
 drivers/net/vhost/rte_eth_vhost.c           | 101 ++-----
 drivers/net/vhost/rte_eth_vhost.h           |  32 +--
 drivers/net/vhost/rte_pmd_vhost_version.map |   3 -
 examples/tep_termination/main.c             |  23 +-
 examples/tep_termination/main.h             |   2 +
 examples/tep_termination/vxlan_setup.c      |   2 +-
 examples/vhost/Makefile                     |   2 +-
 examples/vhost/main.c                       | 100 +++++--
 examples/vhost/main.h                       |  33 ++-
 examples/vhost/virtio_net.c                 | 405 ++++++++++++++++++++++++++
 lib/librte_vhost/Makefile                   |   4 +-
 lib/librte_vhost/fd_man.c                   |   9 +-
 lib/librte_vhost/fd_man.h                   |   2 +-
 lib/librte_vhost/rte_vhost.h                | 423 ++++++++++++++++++++++++++++
 lib/librte_vhost/rte_vhost_version.map      |  17 +-
 lib/librte_vhost/rte_virtio_net.h           | 208 --------------
 lib/librte_vhost/socket.c                   | 222 ++++++++++++---
 lib/librte_vhost/vhost.c                    | 229 ++++++++-------
 lib/librte_vhost/vhost.h                    | 113 +++++---
 lib/librte_vhost/vhost_user.c               | 115 ++++----
 lib/librte_vhost/vhost_user.h               |   2 +-
 lib/librte_vhost/virtio_net.c               |  71 ++---
 25 files changed, 1523 insertions(+), 686 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

-- 
1.9.0

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

* [PATCH v2 01/22] vhost: introduce driver features related APIs
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 02/22] net/vhost: remove feature " Yuanhan Liu
                     ` (21 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Introduce few APIs to set/get/enable/disable driver features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 10 +++-
 lib/librte_vhost/rte_vhost_version.map |  4 ++
 lib/librte_vhost/rte_virtio_net.h      | 51 +++++++++++++++++++
 lib/librte_vhost/socket.c              | 90 ++++++++++++++++++++++++++++++++++
 4 files changed, 153 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index f0862e6..6a4d206 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -53,7 +53,7 @@ vhost library should be able to:
 Vhost API Overview
 ------------------
 
-The following is an overview of the Vhost API functions:
+The following is an overview of some key Vhost API functions:
 
 * ``rte_vhost_driver_register(path, flags)``
 
@@ -110,6 +110,12 @@ The following is an overview of the Vhost API functions:
       of those segments, thus the fewer the segments, the quicker we will get
       the mapping. NOTE: we may speed it by using tree searching in future.
 
+* ``rte_vhost_driver_set_features(path, features)``
+
+  This function sets the feature bits the vhost-user driver supports. The
+  vhost-user driver could be vhost-user net, yet it could be something else,
+  say, vhost-user SCSI.
+
 * ``rte_vhost_driver_session_start()``
 
   This function starts the vhost session loop to handle vhost messages. It
@@ -145,7 +151,7 @@ The following is an overview of the Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_feature_disable/rte_vhost_feature_enable(feature_mask)``
+* ``rte_vhost_driver_disable/enable_features(path, features))``
 
   This function disables/enables some features. For example, it can be used to
   disable mergeable buffers and TSO features, which both are enabled by
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 30b4671..ca6259c 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -34,6 +34,10 @@ DPDK_16.07 {
 DPDK_17.05 {
 	global:
 
+	rte_vhost_driver_disable_features;
+	rte_vhost_driver_enable_features;
+	rte_vhost_driver_get_features;
+	rte_vhost_driver_set_features;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 56829aa..3daf35c 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -94,6 +94,57 @@ struct virtio_net_device_ops {
 /* Unregister vhost driver. This is only meaningful to vhost user. */
 int rte_vhost_driver_unregister(const char *path);
 
+/**
+ * Set the feature bits the vhost-user driver supports.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+
+/**
+ * Enable vhost-user driver features.
+ *
+ * Note that
+ * - the param @features should be a subset of the feature bits provided
+ *   by rte_vhost_driver_set_features().
+ * - it must be invoked before vhost-user negotiation starts.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to enable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+
+/**
+ * Disable vhost-user driver features.
+ *
+ * The two notes at rte_vhost_driver_enable_features() also apply here.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to disable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/**
+ * Get the final feature bits for feature negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  Feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_driver_get_features(const char *path);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
 /* Start vhost driver session blocking loop. */
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 6a30a31..bdccd96 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -63,6 +63,16 @@ struct vhost_user_socket {
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
+
+	/*
+	 * The "supported_features" indicates the feature bits the
+	 * vhost driver supports. The "features" indicates the feature
+	 * bits after the rte_vhost_driver_features_disable/enable().
+	 * It is also the final feature bits used for vhost-user
+	 * features negotiation.
+	 */
+	uint64_t supported_features;
+	uint64_t features;
 };
 
 struct vhost_user_connection {
@@ -475,6 +485,86 @@ struct vhost_user_reconnect_list {
 	return 0;
 }
 
+static struct vhost_user_socket *
+find_vhost_user_socket(const char *path)
+{
+	int i;
+
+	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
+		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
+
+		if (!strcmp(vsocket->path, path))
+			return vsocket;
+	}
+
+	return NULL;
+}
+
+int
+rte_vhost_driver_disable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->features &= ~features;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_enable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		if ((vsocket->supported_features & features) != features) {
+			/*
+			 * trying to enable features the driver doesn't
+			 * support.
+			 */
+			pthread_mutex_unlock(&vhost_user.mutex);
+			return -1;
+		}
+		vsocket->features |= features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_set_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		vsocket->supported_features = features;
+		vsocket->features = features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+uint64_t
+rte_vhost_driver_get_features(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->features : (uint64_t)-1;
+}
+
 /*
  * Register a new vhost-user socket; here we could act as server
  * (the default case), or client (when RTE_VHOST_USER_CLIENT) flag
-- 
1.9.0

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

* [PATCH v2 02/22] net/vhost: remove feature related APIs
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 03/22] vhost: use new APIs to handle features Yuanhan Liu
                     ` (20 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The rte_eth_vhost_feature_disable/enable/get APIs are just a wrapper of
rte_vhost_feature_disable/enable/get. However, the later are going to
be refactored; it's going to take an extra parameter (socket_file path),
to let it be per-device.

Instead of changing those vhost-pmd APIs to adapt to the new vhost APIs,
we could simply remove them, and let vdev to serve this purpose. After
all, vdev options is better for disabling/enabling some features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - write more informative commit log on why they are removed.
    - update release note
---
 doc/guides/rel_notes/release_17_05.rst      |  7 +++++++
 drivers/net/vhost/rte_eth_vhost.c           | 25 ------------------------
 drivers/net/vhost/rte_eth_vhost.h           | 30 -----------------------------
 drivers/net/vhost/rte_pmd_vhost_version.map |  3 ---
 4 files changed, 7 insertions(+), 58 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index bb64428..4e405b1 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -129,6 +129,13 @@ API Changes
 * The LPM ``next_hop`` field is extended from 8 bits to 21 bits for IPv6
   while keeping ABI compatibility.
 
+   * The following vhost-pmd APIs are removed
+
+     * ``rte_eth_vhost_feature_disable``
+     * ``rte_eth_vhost_feature_enable``
+     * ``rte_eth_vhost_feature_get``
+
+
 ABI Changes
 -----------
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a4435da..83063c2 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -965,31 +965,6 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-/**
- * Disable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_disable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_disable(feature_mask);
-}
-
-/**
- * Enable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_enable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_enable(feature_mask);
-}
-
-/* Returns currently supported vhost features */
-uint64_t
-rte_eth_vhost_feature_get(void)
-{
-	return rte_vhost_feature_get();
-}
-
 static const struct eth_dev_ops ops = {
 	.dev_start = eth_dev_start,
 	.dev_stop = eth_dev_stop,
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index 7c98b1a..ea4bce4 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -43,36 +43,6 @@
 
 #include <rte_virtio_net.h>
 
-/**
- * Disable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- * Enable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_enable(uint64_t feature_mask);
-
-/**
- * Returns currently supported vhost features.
- *
- * @return
- *  Vhost features defined in "linux/virtio_net.h".
- */
-uint64_t rte_eth_vhost_feature_get(void);
-
 /*
  * Event description.
  */
diff --git a/drivers/net/vhost/rte_pmd_vhost_version.map b/drivers/net/vhost/rte_pmd_vhost_version.map
index 3d44083..695db85 100644
--- a/drivers/net/vhost/rte_pmd_vhost_version.map
+++ b/drivers/net/vhost/rte_pmd_vhost_version.map
@@ -1,9 +1,6 @@
 DPDK_16.04 {
 	global:
 
-	rte_eth_vhost_feature_disable;
-	rte_eth_vhost_feature_enable;
-	rte_eth_vhost_feature_get;
 	rte_eth_vhost_get_queue_event;
 
 	local: *;
-- 
1.9.0

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

* [PATCH v2 03/22] vhost: use new APIs to handle features
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 02/22] net/vhost: remove feature " Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
                     ` (19 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/tep_termination/main.c        |  4 +++-
 examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
 lib/librte_vhost/rte_vhost_version.map |  3 ---
 lib/librte_vhost/rte_virtio_net.h      | 13 ----------
 lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
 lib/librte_vhost/vhost.c               | 42 ---------------------------------
 lib/librte_vhost/vhost.h               | 21 +++++++++++++++++
 lib/librte_vhost/vhost_user.c          |  8 +++----
 8 files changed, 77 insertions(+), 80 deletions(-)

diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 20dafdb..8097dcd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1248,12 +1248,14 @@ static inline void __attribute__((always_inline))
 		rte_eal_remote_launch(switch_worker,
 			mbuf_pool, lcore_id);
 	}
-	rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
 	ret = rte_vhost_driver_register((char *)&dev_basename, 0);
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "failed to register vhost driver.\n");
 
+	rte_vhost_driver_disable_features(dev_basename,
+		1ULL << VIRTIO_NET_F_MRG_RXBUF);
+
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
 
 	rte_vhost_driver_session_start();
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4789947..972a6a8 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -328,16 +328,6 @@ struct mbuf_table {
 
 	if (port >= rte_eth_dev_count()) return -1;
 
-	if (enable_tx_csum == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM);
-
-	if (enable_tso == 0) {
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
-	}
-
 	rx_rings = (uint16_t)dev_info.max_rx_queues;
 	/* Configure ethernet device. */
 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
@@ -531,7 +521,6 @@ struct mbuf_table {
 			vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode =
 				ETH_VMDQ_ACCEPT_BROADCAST |
 				ETH_VMDQ_ACCEPT_MULTICAST;
-			rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX);
 
 			break;
 
@@ -1509,9 +1498,6 @@ static inline void __attribute__((always_inline))
 	RTE_LCORE_FOREACH_SLAVE(lcore_id)
 		rte_eal_remote_launch(switch_worker, NULL, lcore_id);
 
-	if (mergeable == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
-
 	if (client_mode)
 		flags |= RTE_VHOST_USER_CLIENT;
 
@@ -1520,13 +1506,38 @@ static inline void __attribute__((always_inline))
 
 	/* Register vhost user driver to handle vhost messages. */
 	for (i = 0; i < nb_sockets; i++) {
-		ret = rte_vhost_driver_register
-				(socket_files + i * PATH_MAX, flags);
+		char *file = socket_files + i * PATH_MAX;
+		ret = rte_vhost_driver_register(file, flags);
 		if (ret != 0) {
 			unregister_drivers(i);
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+		if (mergeable == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_MRG_RXBUF);
+		}
+
+		if (enable_tx_csum == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_CSUM);
+		}
+
+		if (enable_tso == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO6);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO6);
+		}
+
+		if (promiscuous) {
+			rte_vhost_driver_enable_features(file,
+				1ULL << VIRTIO_NET_F_CTRL_RX);
+		}
 	}
 
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index ca6259c..1150017 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -7,9 +7,6 @@ DPDK_2.0 {
 	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
-	rte_vhost_feature_disable;
-	rte_vhost_feature_enable;
-	rte_vhost_feature_get;
 
 	local: *;
 };
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 3daf35c..5dadd3d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -70,19 +70,6 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
-/**
- *  Disable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- *  Enable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_enable(uint64_t feature_mask);
-
-/* Returns currently supported vhost features */
-uint64_t rte_vhost_feature_get(void);
-
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index bdccd96..bbb4112 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -562,7 +562,13 @@ struct vhost_user_reconnect_list {
 	vsocket = find_vhost_user_socket(path);
 	pthread_mutex_unlock(&vhost_user.mutex);
 
-	return vsocket ? vsocket->features : (uint64_t)-1;
+	if (!vsocket) {
+		RTE_LOG(ERR, VHOST_CONFIG,
+			"socket file %s is not registered yet.\n", path);
+		return 0;
+	} else {
+		return vsocket->features;
+	}
 }
 
 /*
@@ -595,6 +601,21 @@ struct vhost_user_reconnect_list {
 	vsocket->connfd = -1;
 	vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
 
+	/*
+	 * Set the supported features correctly for the builtin vhost-user
+	 * net driver.
+	 *
+	 * Applications know nothing about features the builtin virtio net
+	 * driver (virtio_net.c) supports, thus it's not possible for them
+	 * to invoke rte_vhost_driver_set_features(). To workaround it, here
+	 * we set it unconditionaly. If the application want to implement
+	 * another vhost-user driver (say SCSI), it should call the
+	 * rte_vhost_driver_set_features(), which will overwrite following
+	 * two values.
+	 */
+	vsocket->supported_features = VIRTIO_NET_SUPPORTED_FEATURES;
+	vsocket->features           = VIRTIO_NET_SUPPORTED_FEATURES;
+
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
 		if (vsocket->reconnect && reconn_tid == 0) {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index dfb08db..7b40a92 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -49,28 +49,6 @@
 
 #include "vhost.h"
 
-#define VHOST_USER_F_PROTOCOL_FEATURES	30
-
-/* Features supported by this lib. */
-#define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
-				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
-				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
-				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
-				(1ULL << VIRTIO_NET_F_MQ)      | \
-				(1ULL << VIRTIO_F_VERSION_1)   | \
-				(1ULL << VHOST_F_LOG_ALL)      | \
-				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
-				(1ULL << VIRTIO_NET_F_CSUM)    | \
-				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
-				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
-				(1ULL << VIRTIO_NET_F_MTU))
-
-uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
-
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
 /* device ops to add/remove device to/from data core. */
@@ -419,26 +397,6 @@ struct virtio_net *
 	return 0;
 }
 
-uint64_t rte_vhost_feature_get(void)
-{
-	return VHOST_FEATURES;
-}
-
-int rte_vhost_feature_disable(uint64_t feature_mask)
-{
-	VHOST_FEATURES = VHOST_FEATURES & ~feature_mask;
-	return 0;
-}
-
-int rte_vhost_feature_enable(uint64_t feature_mask)
-{
-	if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) {
-		VHOST_FEATURES = VHOST_FEATURES | feature_mask;
-		return 0;
-	}
-	return -1;
-}
-
 /*
  * Register ops so that we can add/remove device to data core.
  */
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index daa9328..692691b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -133,6 +133,27 @@ struct vhost_virtqueue {
  #define VIRTIO_F_VERSION_1 32
 #endif
 
+#define VHOST_USER_F_PROTOCOL_FEATURES	30
+
+/* Features supported by this builtin vhost-user net driver. */
+#define VIRTIO_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
+				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
+				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+				(1ULL << VIRTIO_NET_F_MQ)      | \
+				(1ULL << VIRTIO_F_VERSION_1)   | \
+				(1ULL << VHOST_F_LOG_ALL)      | \
+				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
+				(1ULL << VIRTIO_NET_F_CSUM)    | \
+				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
+				(1ULL << VIRTIO_NET_F_MTU))
+
+
 struct guest_page {
 	uint64_t guest_phys_addr;
 	uint64_t host_phys_addr;
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7c6a5f7..d630098 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -147,9 +147,9 @@
  * The features that we support are requested.
  */
 static uint64_t
-vhost_user_get_features(void)
+vhost_user_get_features(struct virtio_net *dev)
 {
-	return VHOST_FEATURES;
+	return rte_vhost_driver_get_features(dev->ifname);
 }
 
 /*
@@ -158,7 +158,7 @@
 static int
 vhost_user_set_features(struct virtio_net *dev, uint64_t features)
 {
-	if (features & ~VHOST_FEATURES)
+	if (features & ~rte_vhost_driver_get_features(dev->ifname))
 		return -1;
 
 	dev->features = features;
@@ -1006,7 +1006,7 @@
 
 	switch (msg.request) {
 	case VHOST_USER_GET_FEATURES:
-		msg.payload.u64 = vhost_user_get_features();
+		msg.payload.u64 = vhost_user_get_features(dev);
 		msg.size = sizeof(msg.payload.u64);
 		send_vhost_message(fd, &msg);
 		break;
-- 
1.9.0

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

* [PATCH v2 04/22] vhost: make notify ops per vhost driver
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (2 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 03/22] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 05/22] vhost: export guest memory regions Yuanhan Liu
                     ` (18 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Assume there is an application both support vhost-user net and
vhost-user scsi, the callback should be different. Making notify
ops per vhost driver allow application define different set of
callbacks for different driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v2: - check the return value of callback_register and callback_get
    - update release note
---
 doc/guides/prog_guide/vhost_lib.rst    |  2 +-
 doc/guides/rel_notes/release_17_05.rst |  3 +++
 drivers/net/vhost/rte_eth_vhost.c      | 20 +++++++++++---------
 examples/tep_termination/main.c        |  7 ++++++-
 examples/vhost/main.c                  |  9 +++++++--
 lib/librte_vhost/rte_virtio_net.h      |  3 ++-
 lib/librte_vhost/socket.c              | 32 ++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 16 +---------------
 lib/librte_vhost/vhost.h               |  5 ++++-
 lib/librte_vhost/vhost_user.c          | 22 ++++++++++++++++------
 10 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 6a4d206..40f3b3b 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 4e405b1..dfa636d 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -135,6 +135,9 @@ API Changes
      * ``rte_eth_vhost_feature_enable``
      * ``rte_eth_vhost_feature_get``
 
+   * The vhost API ``rte_vhost_driver_callback_register(ops)`` takes one
+     more argument: ``rte_vhost_driver_callback_register(path, ops)``.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 83063c2..f6ad616 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -669,6 +669,12 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
+static struct virtio_net_device_ops vhost_ops = {
+	.new_device          = new_device,
+	.destroy_device      = destroy_device,
+	.vring_state_changed = vring_state_changed,
+};
+
 int
 rte_eth_vhost_get_queue_event(uint8_t port_id,
 		struct rte_eth_vhost_queue_event *event)
@@ -738,15 +744,6 @@ struct vhost_xstats_name_off {
 static void *
 vhost_driver_session(void *param __rte_unused)
 {
-	static struct virtio_net_device_ops vhost_ops;
-
-	/* set vhost arguments */
-	vhost_ops.new_device = new_device;
-	vhost_ops.destroy_device = destroy_device;
-	vhost_ops.vring_state_changed = vring_state_changed;
-	if (rte_vhost_driver_callback_register(&vhost_ops) < 0)
-		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
-
 	/* start event handling */
 	rte_vhost_driver_session_start();
 
@@ -1079,6 +1076,11 @@ struct vhost_xstats_name_off {
 	if (rte_vhost_driver_register(iface_name, flags))
 		goto error;
 
+	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
+		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
+		goto error;
+	}
+
 	/* We need only one message handling thread */
 	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
 		if (vhost_driver_session_start())
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 8097dcd..18b977e 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1256,7 +1256,12 @@ static inline void __attribute__((always_inline))
 	rte_vhost_driver_disable_features(dev_basename,
 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+	ret = rte_vhost_driver_callback_register(dev_basename,
+		&virtio_net_device_ops);
+	if (ret != 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to register vhost driver callbacks.\n");
+	}
 
 	rte_vhost_driver_session_start();
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 972a6a8..72a9d69 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1538,9 +1538,14 @@ static inline void __attribute__((always_inline))
 			rte_vhost_driver_enable_features(file,
 				1ULL << VIRTIO_NET_F_CTRL_RX);
 		}
-	}
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+		ret = rte_vhost_driver_callback_register(file,
+			&virtio_net_device_ops);
+		if (ret != 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to register vhost driver callbacks.\n");
+		}
+	}
 
 	rte_vhost_driver_session_start();
 	return 0;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5dadd3d..67bd125 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -133,7 +133,8 @@ struct virtio_net_device_ops {
 uint64_t rte_vhost_driver_get_features(const char *path);
 
 /* Register callbacks. */
-int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
+int rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index bbb4112..8431511 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -73,6 +73,8 @@ struct vhost_user_socket {
 	 */
 	uint64_t supported_features;
 	uint64_t features;
+
+	struct virtio_net_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -718,6 +720,36 @@ struct vhost_user_reconnect_list {
 	return -1;
 }
 
+/*
+ * Register ops so that we can add/remove device to data core.
+ */
+int
+rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->notify_ops = ops;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+struct virtio_net_device_ops const *
+vhost_driver_callback_get(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->notify_ops : NULL;
+}
+
 int
 rte_vhost_driver_session_start(void)
 {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7b40a92..7d7bb3c 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -51,9 +51,6 @@
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* device ops to add/remove device to/from data core. */
-struct virtio_net_device_ops const *notify_ops;
-
 struct virtio_net *
 get_device(int vid)
 {
@@ -253,7 +250,7 @@ struct virtio_net *
 
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(vid);
+		dev->notify_ops->destroy_device(vid);
 	}
 
 	cleanup_device(dev, 1);
@@ -396,14 +393,3 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
-
-/*
- * Register ops so that we can add/remove device to data core.
- */
-int
-rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
-{
-	notify_ops = ops;
-
-	return 0;
-}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 692691b..6186216 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -185,6 +185,8 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
+	struct virtio_net_device_ops const *notify_ops;
+
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
 	struct guest_page       *guest_pages;
@@ -288,7 +290,6 @@ static inline phys_addr_t __attribute__((always_inline))
 	return 0;
 }
 
-struct virtio_net_device_ops const *notify_ops;
 struct virtio_net *get_device(int vid);
 
 int vhost_new_device(void);
@@ -301,6 +302,8 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
+struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+
 /*
  * Backend-specific cleanup.
  *
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index d630098..0cadd79 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -135,7 +135,7 @@
 {
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	cleanup_device(dev, 0);
@@ -503,7 +503,7 @@
 	/* Remove from the data plane. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	if (dev->mem) {
@@ -687,7 +687,7 @@
 						"dequeue zero copy is enabled\n");
 			}
 
-			if (notify_ops->new_device(dev->vid) == 0)
+			if (dev->notify_ops->new_device(dev->vid) == 0)
 				dev->flags |= VIRTIO_DEV_RUNNING;
 		}
 	}
@@ -721,7 +721,7 @@
 	/* We have to stop the queue (virtio) if it is running. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	dev->flags &= ~VIRTIO_DEV_READY;
@@ -763,8 +763,8 @@
 		"set queue enable: %d to qp idx: %d\n",
 		enable, state->index);
 
-	if (notify_ops->vring_state_changed)
-		notify_ops->vring_state_changed(dev->vid, state->index, enable);
+	if (dev->notify_ops->vring_state_changed)
+		dev->notify_ops->vring_state_changed(dev->vid, state->index, enable);
 
 	dev->virtqueue[state->index]->enabled = enable;
 
@@ -978,6 +978,16 @@
 	if (dev == NULL)
 		return -1;
 
+	if (!dev->notify_ops) {
+		dev->notify_ops = vhost_driver_callback_get(dev->ifname);
+		if (!dev->notify_ops) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to get callback ops for driver %s\n",
+				dev->ifname);
+			return -1;
+		}
+	}
+
 	ret = read_vhost_message(fd, &msg);
 	if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
 		if (ret < 0)
-- 
1.9.0

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

* [PATCH v2 05/22] vhost: export guest memory regions
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (3 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
                     ` (17 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Some vhost-user driver may need this info to setup its own page tables
for GPA (guest physical addr) to HPA (host physical addr) translation.
SPDK (Storage Performance Development Kit) is one example.

Besides, by exporting this memory info, we could also export the
gpa_to_vva() as an inline function, which helps for performance.
Otherwise, it has to be referenced indirectly by a "vid".

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 38 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 23 ++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 28 ++-----------------------
 lib/librte_vhost/vhost_user.c          | 12 +++++------
 5 files changed, 70 insertions(+), 32 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 1150017..664a5f3 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -35,6 +35,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 67bd125..5a91f97 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -59,6 +59,28 @@
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
 /**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+/**
  * Device and vring operations.
  */
 struct virtio_net_device_ops {
@@ -244,4 +266,20 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
 uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
 
+/**
+ * Get guest mem table: a list of memory regions.
+ *
+ * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
+ * guest memory regions. Application should free it at destroy_device()
+ * callback.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param mem
+ *  To store the returned mem regions
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7d7bb3c..2b41652 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -359,6 +359,29 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
+{
+	struct virtio_net *dev;
+	struct rte_vhost_memory *m;
+	size_t size;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
+	m = malloc(size);
+	if (!m)
+		return -1;
+
+	m->nregions = dev->mem->nregions;
+	memcpy(m->regions, dev->mem->regions, size);
+	*mem = m;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6186216..6d1986a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -166,7 +166,7 @@ struct guest_page {
  */
 struct virtio_net {
 	/* Frontend (QEMU) memory and memory region information */
-	struct virtio_memory	*mem;
+	struct rte_vhost_memory	*mem;
 	uint64_t		features;
 	uint64_t		protocol_features;
 	int			vid;
@@ -192,30 +192,6 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct virtio_memory_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct virtio_memory {
-	uint32_t nregions;
-	struct virtio_memory_region regions[0];
-};
-
-
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
@@ -255,7 +231,7 @@ struct virtio_memory {
 static inline uint64_t __attribute__((always_inline))
 gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	for (i = 0; i < dev->mem->nregions; i++) {
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 0cadd79..70093a4 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -92,7 +92,7 @@
 free_mem_region(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 
 	if (!dev || !dev->mem)
 		return;
@@ -304,7 +304,7 @@
 static uint64_t
 qva_to_vva(struct virtio_net *dev, uint64_t qva)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	/* Find the region where the address lives. */
@@ -432,7 +432,7 @@
 }
 
 static void
-add_guest_pages(struct virtio_net *dev, struct virtio_memory_region *reg,
+add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 		uint64_t page_size)
 {
 	uint64_t reg_size = reg->size;
@@ -492,7 +492,7 @@
 vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
 	struct VhostUserMemory memory = pmsg->payload.memory;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	void *mmap_addr;
 	uint64_t mmap_size;
 	uint64_t mmap_offset;
@@ -519,8 +519,8 @@
 						sizeof(struct guest_page));
 	}
 
-	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct virtio_memory) +
-		sizeof(struct virtio_memory_region) * memory.nregions, 0);
+	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct rte_vhost_memory) +
+		sizeof(struct rte_vhost_mem_region) * memory.nregions, 0);
 	if (dev->mem == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"(%d) failed to allocate memory for dev->mem\n",
-- 
1.9.0

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

* [PATCH v2 06/22] vhost: introduce API to fetch negotiated features
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (4 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 05/22] vhost: export guest memory regions Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 07/22] vhost: export vhost vring info Yuanhan Liu
                     ` (16 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  2 ++
 lib/librte_vhost/rte_virtio_net.h      | 10 ++++++++++
 lib/librte_vhost/vhost.c               | 12 ++++++++++++
 3 files changed, 24 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 664a5f3..e21b788 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -37,5 +37,7 @@ DPDK_17.05 {
 	rte_vhost_driver_set_features;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
+	rte_vhost_get_negotiated_features
+	rte_vhost_get_vhost_memory;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5a91f97..57e57e3 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -154,6 +154,16 @@ struct virtio_net_device_ops {
  */
 uint64_t rte_vhost_driver_get_features(const char *path);
 
+/**
+ * Get the feature bits after negotiation
+ *
+ * @param vid
+ *  Vhost device ID
+ * @return
+ *  Negotiated feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_get_negotiated_features(int vid);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct virtio_net_device_ops const * const ops);
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 2b41652..08dccfb 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -359,6 +359,18 @@ struct virtio_net *
 	return 0;
 }
 
+uint64_t
+rte_vhost_get_negotiated_features(int vid)
+{
+	struct virtio_net *dev;
+
+	dev = get_device(vid);
+	if (!dev)
+		return 0;
+
+	return dev->features;
+}
+
 int
 rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
 {
-- 
1.9.0

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

* [PATCH v2 07/22] vhost: export vhost vring info
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (5 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
                     ` (15 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v2: - fix off-by-one check
    - add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 26 ++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               |  2 ++
 4 files changed, 59 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index e21b788..28664a4 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -39,5 +39,6 @@ DPDK_17.05 {
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
+	rte_vhost_get_vhost_vring;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 57e57e3..5142337 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -80,6 +80,17 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[0];
 };
 
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
 /**
  * Device and vring operations.
  */
@@ -292,4 +303,19 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
  */
 int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
 
+/**
+ * Get guest vring info, including the vring address, vring size, etc.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 08dccfb..6fe613b 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -394,6 +394,36 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			  struct rte_vhost_vring *vring)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return -1;
+
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return -1;
+
+	vring->desc  = vq->desc;
+	vring->avail = vq->avail;
+	vring->used  = vq->used;
+	vring->log_guest_addr  = vq->log_guest_addr;
+
+	vring->callfd  = vq->callfd;
+	vring->kickfd  = vq->kickfd;
+	vring->size    = vq->size;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6d1986a..68ca197 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -120,6 +120,8 @@ struct vhost_virtqueue {
 #ifndef VIRTIO_NET_F_MQ
  #define VIRTIO_NET_F_MQ		22
 #endif
+
+#define VHOST_MAX_VRING			0x100
 #define VHOST_MAX_QUEUE_PAIRS		0x80
 
 #ifndef VIRTIO_NET_F_MTU
-- 
1.9.0

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

* [PATCH v2 08/22] vhost: export API to translate gpa to vva
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (6 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 09/22] vhost: turn queue pair to vring Yuanhan Liu
                     ` (14 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 28 ++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 19 -------------------
 lib/librte_vhost/virtio_net.c          | 23 +++++++++++++----------
 4 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 28664a4..7df7af6 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -40,5 +40,6 @@ DPDK_17.05 {
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5142337..36674bb 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -103,6 +103,34 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
+/**
+ * Convert guest physical address to host virtual address
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 68ca197..b5c5046 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -229,25 +229,6 @@ struct virtio_net {
 #define MAX_VHOST_DEVICE	1024
 extern struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* Convert guest physical Address to host virtual address */
-static inline uint64_t __attribute__((always_inline))
-gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < dev->mem->nregions; i++) {
-		reg = &dev->mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
 /* Convert guest physical address to host physical address */
 static inline phys_addr_t __attribute__((always_inline))
 gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 337470d..6b9b4c3 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -199,7 +199,7 @@ static inline int __attribute__((always_inline))
 	uint16_t nr_desc = 1;
 
 	desc = &descs[desc_idx];
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	/*
 	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
 	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
@@ -239,7 +239,7 @@ static inline int __attribute__((always_inline))
 				return -1;
 
 			desc = &descs[desc->next];
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -323,7 +323,8 @@ static inline uint32_t __attribute__((always_inline))
 		int err;
 
 		if (vq->desc[desc_idx].flags & VRING_DESC_F_INDIRECT) {
-			descs = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			descs = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_idx].addr);
 			if (unlikely(!descs)) {
 				count = i;
@@ -383,7 +384,7 @@ static inline int __attribute__((always_inline))
 
 	if (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) {
 		descs = (struct vring_desc *)(uintptr_t)
-					gpa_to_vva(dev, vq->desc[idx].addr);
+			rte_vhost_gpa_to_vva(dev->mem, vq->desc[idx].addr);
 		if (unlikely(!descs))
 			return -1;
 
@@ -473,7 +474,7 @@ static inline int __attribute__((always_inline))
 	if (unlikely(m == NULL))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, buf_vec[vec_idx].buf_addr);
 	if (buf_vec[vec_idx].buf_len < dev->vhost_hlen || !desc_addr)
 		return -1;
 
@@ -495,7 +496,8 @@ static inline int __attribute__((always_inline))
 		/* done with current desc buf, get the next one */
 		if (desc_avail == 0) {
 			vec_idx++;
-			desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem,
+					buf_vec[vec_idx].buf_addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -798,7 +800,7 @@ static inline int __attribute__((always_inline))
 			(desc->flags & VRING_DESC_F_INDIRECT))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	if (unlikely(!desc_addr))
 		return -1;
 
@@ -818,7 +820,7 @@ static inline int __attribute__((always_inline))
 		if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 			return -1;
 
-		desc_addr = gpa_to_vva(dev, desc->addr);
+		desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 		if (unlikely(!desc_addr))
 			return -1;
 
@@ -882,7 +884,7 @@ static inline int __attribute__((always_inline))
 			if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 				return -1;
 
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -1113,7 +1115,8 @@ static inline bool __attribute__((always_inline))
 			rte_prefetch0(&vq->desc[desc_indexes[i + 1]]);
 
 		if (vq->desc[desc_indexes[i]].flags & VRING_DESC_F_INDIRECT) {
-			desc = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			desc = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_indexes[i]].addr);
 			if (unlikely(!desc))
 				break;
-- 
1.9.0

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

* [PATCH v2 09/22] vhost: turn queue pair to vring
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (7 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 10/22] vhost: export the number of vrings Yuanhan Liu
                     ` (13 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The queue pair is very virtio-net specific, other devices don't have
such concept. To make it generic, we should log the number of vrings
instead of the number of queue pairs.

This patch just does a simple convert, a later patch would export the
number of vrings to applications.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: enable all vrings by unconditionally
---
 lib/librte_vhost/vhost.c      | 80 +++++++++++++++----------------------------
 lib/librte_vhost/vhost.h      |  4 +--
 lib/librte_vhost/vhost_user.c | 28 +++++----------
 lib/librte_vhost/virtio_net.c | 10 +++---
 4 files changed, 42 insertions(+), 80 deletions(-)

diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 6fe613b..70477c6 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -84,10 +84,8 @@ struct virtio_net *
 
 	vhost_backend_cleanup(dev);
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ], destroy);
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ], destroy);
-	}
+	for (i = 0; i < dev->nr_vring; i++)
+		cleanup_vq(dev->virtqueue[i], destroy);
 }
 
 /*
@@ -97,24 +95,21 @@ struct virtio_net *
 free_device(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct vhost_virtqueue *rxq, *txq;
+	struct vhost_virtqueue *vq;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rxq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		txq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		rte_free(rxq->shadow_used_ring);
-		rte_free(txq->shadow_used_ring);
+		rte_free(vq->shadow_used_ring);
 
-		/* rxq and txq are allocated together as queue-pair */
-		rte_free(rxq);
+		rte_free(vq);
 	}
 
 	rte_free(dev);
 }
 
 static void
-init_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+init_vring_queue(struct vhost_virtqueue *vq)
 {
 	memset(vq, 0, sizeof(struct vhost_virtqueue));
 
@@ -124,69 +119,48 @@ struct virtio_net *
 	/* Backends are set to -1 indicating an inactive device. */
 	vq->backend = -1;
 
-	/* always set the default vq pair to enabled */
-	if (qp_idx == 0)
-		vq->enabled = 1;
+	/*
+	 * always set the vq to enabled; this is to keep compatibility
+	 * with the old QEMU, whereas there is no SET_VRING_ENABLE message.
+	 */
+	vq->enabled = 1;
 
 	TAILQ_INIT(&vq->zmbuf_list);
 }
 
 static void
-init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
-static void
-reset_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+reset_vring_queue(struct vhost_virtqueue *vq)
 {
 	int callfd;
 
 	callfd = vq->callfd;
-	init_vring_queue(vq, qp_idx);
+	init_vring_queue(vq);
 	vq->callfd = callfd;
 }
 
-static void
-reset_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
 int
-alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
+alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {
-	struct vhost_virtqueue *virtqueue = NULL;
-	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
-	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
+	struct vhost_virtqueue *vq;
 
-	virtqueue = rte_malloc(NULL,
-			       sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);
-	if (virtqueue == NULL) {
+	vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
+	if (vq == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
-			"Failed to allocate memory for virt qp:%d.\n", qp_idx);
+			"Failed to allocate memory for vring:%u.\n", vring_idx);
 		return -1;
 	}
 
-	dev->virtqueue[virt_rx_q_idx] = virtqueue;
-	dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
-
-	init_vring_queue_pair(dev, qp_idx);
+	dev->virtqueue[vring_idx] = vq;
+	init_vring_queue(vq);
 
-	dev->virt_qp_nb += 1;
+	dev->nr_vring += 1;
 
 	return 0;
 }
 
 /*
  * Reset some variables in device structure, while keeping few
- * others untouched, such as vid, ifname, virt_qp_nb: they
+ * others untouched, such as vid, ifname, nr_vring: they
  * should be same unless the device is removed.
  */
 void
@@ -198,8 +172,8 @@ struct virtio_net *
 	dev->protocol_features = 0;
 	dev->flags = 0;
 
-	for (i = 0; i < dev->virt_qp_nb; i++)
-		reset_vring_queue_pair(dev, i);
+	for (i = 0; i < dev->nr_vring; i++)
+		reset_vring_queue(dev->virtqueue[i]);
 }
 
 /*
@@ -340,7 +314,7 @@ struct virtio_net *
 	if (dev == NULL)
 		return 0;
 
-	return dev->virt_qp_nb;
+	return dev->nr_vring / 2;
 }
 
 int
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index b5c5046..84e379a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -176,7 +176,7 @@ struct virtio_net {
 	uint16_t		vhost_hlen;
 	/* to tell if we need broadcast rarp packet */
 	rte_atomic16_t		broadcast_rarp;
-	uint32_t		virt_qp_nb;
+	uint32_t		nr_vring;
 	int			dequeue_zero_copy;
 	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
@@ -256,7 +256,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void reset_device(struct virtio_net *dev);
 void vhost_destroy_device(int);
 
-int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
+int alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 70093a4..f841c9b 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -227,13 +227,6 @@
 	struct vhost_virtqueue *old_vq, *vq;
 	int ret;
 
-	/*
-	 * vq is allocated on pairs, we should try to do realloc
-	 * on first queue of one queue pair only.
-	 */
-	if (index % VIRTIO_QNUM != 0)
-		return dev;
-
 	old_dev = dev;
 	vq = old_vq = dev->virtqueue[index];
 
@@ -251,8 +244,7 @@
 	if (oldnode != newnode) {
 		RTE_LOG(INFO, VHOST_CONFIG,
 			"reallocate vq from %d to %d node\n", oldnode, newnode);
-		vq = rte_malloc_socket(NULL, sizeof(*vq) * VIRTIO_QNUM, 0,
-				       newnode);
+		vq = rte_malloc_socket(NULL, sizeof(*vq), 0, newnode);
 		if (!vq)
 			return dev;
 
@@ -284,7 +276,6 @@
 
 out:
 	dev->virtqueue[index] = vq;
-	dev->virtqueue[index + 1] = vq + 1;
 	vhost_devices[dev->vid] = dev;
 
 	return dev;
@@ -615,14 +606,13 @@
 static int
 virtio_is_ready(struct virtio_net *dev)
 {
-	struct vhost_virtqueue *rvq, *tvq;
+	struct vhost_virtqueue *vq;
 	uint32_t i;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		tvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(rvq) || !vq_is_ready(tvq)) {
+		if (!vq_is_ready(vq)) {
 			RTE_LOG(INFO, VHOST_CONFIG,
 				"virtio is not ready for processing.\n");
 			return 0;
@@ -934,7 +924,6 @@
 vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev, VhostUserMsg *msg)
 {
 	uint16_t vring_idx;
-	uint16_t qp_idx;
 
 	switch (msg->request) {
 	case VHOST_USER_SET_VRING_KICK:
@@ -954,17 +943,16 @@
 		return 0;
 	}
 
-	qp_idx = vring_idx / VIRTIO_QNUM;
-	if (qp_idx >= VHOST_MAX_QUEUE_PAIRS) {
+	if (vring_idx >= VHOST_MAX_VRING) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"invalid vring index: %u\n", vring_idx);
 		return -1;
 	}
 
-	if (dev->virtqueue[qp_idx])
+	if (dev->virtqueue[vring_idx])
 		return 0;
 
-	return alloc_vring_queue_pair(dev, qp_idx);
+	return alloc_vring_queue(dev, vring_idx);
 }
 
 int
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 6b9b4c3..8ed2b93 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -86,9 +86,9 @@ static inline void __attribute__((always_inline))
 }
 
 static bool
-is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t qp_nb)
+is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
 {
-	return (is_tx ^ (idx & 1)) == 0 && idx < qp_nb * VIRTIO_QNUM;
+	return (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;
 }
 
 static inline void __attribute__((always_inline))
@@ -283,7 +283,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint32_t i, sz;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -554,7 +554,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint16_t avail_head;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -1019,7 +1019,7 @@ static inline bool __attribute__((always_inline))
 	if (!dev)
 		return 0;
 
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
-- 
1.9.0

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

* [PATCH v2 10/22] vhost: export the number of vrings
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (8 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 11/22] vhost: move the device ready check at proper place Yuanhan Liu
                     ` (12 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_get_queue_num() for telling how many vrings.
However, the return value is the number of "queue pairs", which is
very virtio-net specific. To make it generic, we should return the
number of vrings instead, and let the driver do the proper translation.
Say, virtio-net driver could turn it to the number of queue pairs by
dividing 2.

Meanwhile, mark rte_vhost_get_queue_num as deprecated.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst |  3 +++
 drivers/net/vhost/rte_eth_vhost.c      |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 17 +++++++++++++++++
 lib/librte_vhost/vhost.c               | 11 +++++++++++
 5 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index dfa636d..eca9451 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -138,6 +138,9 @@ API Changes
    * The vhost API ``rte_vhost_driver_callback_register(ops)`` takes one
      more argument: ``rte_vhost_driver_callback_register(path, ops)``.
 
+   * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
+     ``rte_vhost_get_vring_num`` should be used.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index f6ad616..dc583e4 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -569,7 +569,7 @@ struct vhost_xstats_name_off {
 		vq->port = eth_dev->data->port_id;
 	}
 
-	for (i = 0; i < rte_vhost_get_queue_num(vid) * VIRTIO_QNUM; i++)
+	for (i = 0; i < rte_vhost_get_vring_num(vid); i++)
 		rte_vhost_enable_guest_notification(vid, i, 0);
 
 	rte_vhost_get_mtu(vid, &eth_dev->data->mtu);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 7df7af6..ff62c39 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -40,6 +40,7 @@ DPDK_17.05 {
 	rte_vhost_get_negotiated_features
 	rte_vhost_get_vhost_memory;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 36674bb..f700d2f 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -237,17 +237,34 @@ int rte_vhost_driver_callback_register(const char *path,
 int rte_vhost_get_numa_node(int vid);
 
 /**
+ * @deprecated
  * Get the number of queues the device supports.
  *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
  * @param vid
  *  virtio-net device ID
  *
  * @return
  *  The number of queues, 0 on failure
  */
+__rte_deprecated
 uint32_t rte_vhost_get_queue_num(int vid);
 
 /**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
  * Get the virtio net device's ifname, which is the vhost-user socket
  * file path.
  *
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 70477c6..74ae3b2 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -317,6 +317,17 @@ struct virtio_net *
 	return dev->nr_vring / 2;
 }
 
+uint16_t
+rte_vhost_get_vring_num(int vid)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return 0;
+
+	return dev->nr_vring;
+}
+
 int
 rte_vhost_get_ifname(int vid, char *buf, size_t len)
 {
-- 
1.9.0

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

* [PATCH v2 11/22] vhost: move the device ready check at proper place
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (9 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
                     ` (11 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Currently, we check vq->desc, vq->kickfd and vq->callfd to know whether
a virtio device is ready or not. However, we only do it when handling
SET_VRING_KICK message, which could be wrong if a vhost-user frontend
send SET_VRING_KICK first and SET_VRING_CALL later.

To work for all possible vhost-user frontend implementations, we could
move the ready check at the end of vhost-user message handler.

Meanwhile, since we do the check more often than before, the "virtio
not ready" message is dropped, to not flood the screen.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/vhost_user.c | 40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index f841c9b..7f93f27 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -609,14 +609,14 @@
 	struct vhost_virtqueue *vq;
 	uint32_t i;
 
+	if (dev->nr_vring == 0)
+		return 0;
+
 	for (i = 0; i < dev->nr_vring; i++) {
 		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(vq)) {
-			RTE_LOG(INFO, VHOST_CONFIG,
-				"virtio is not ready for processing.\n");
+		if (!vq_is_ready(vq))
 			return 0;
-		}
 	}
 
 	RTE_LOG(INFO, VHOST_CONFIG,
@@ -645,10 +645,6 @@
 	vq->callfd = file.fd;
 }
 
-/*
- *  In vhost-user, when we receive kick message, will test whether virtio
- *  device is ready for packet processing.
- */
 static void
 vhost_user_set_vring_kick(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
@@ -667,20 +663,6 @@
 	if (vq->kickfd >= 0)
 		close(vq->kickfd);
 	vq->kickfd = file.fd;
-
-	if (virtio_is_ready(dev)) {
-		dev->flags |= VIRTIO_DEV_READY;
-
-		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
-			if (dev->dequeue_zero_copy) {
-				RTE_LOG(INFO, VHOST_CONFIG,
-						"dequeue zero copy is enabled\n");
-			}
-
-			if (dev->notify_ops->new_device(dev->vid) == 0)
-				dev->flags |= VIRTIO_DEV_RUNNING;
-		}
-	}
 }
 
 static void
@@ -1102,5 +1084,19 @@
 		send_vhost_message(fd, &msg);
 	}
 
+	if (!(dev->flags & VIRTIO_DEV_RUNNING) && virtio_is_ready(dev)) {
+		dev->flags |= VIRTIO_DEV_READY;
+
+		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
+			if (dev->dequeue_zero_copy) {
+				RTE_LOG(INFO, VHOST_CONFIG,
+						"dequeue zero copy is enabled\n");
+			}
+
+			if (dev->notify_ops->new_device(dev->vid) == 0)
+				dev->flags |= VIRTIO_DEV_RUNNING;
+		}
+	}
+
 	return 0;
 }
-- 
1.9.0

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

* [PATCH v2 12/22] vhost: drop the Rx and Tx queue macro
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (10 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 11/22] vhost: move the device ready check at proper place Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 13/22] vhost: do not include net specific headers Yuanhan Liu
                     ` (10 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

They are virtio-net specific and should be defined inside the virtio-net
driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 6 ++++++
 drivers/net/vhost/rte_eth_vhost.c      | 2 ++
 examples/tep_termination/main.h        | 2 ++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 3 ---
 5 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index eca9451..55bf136 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -141,6 +141,12 @@ API Changes
    * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
      ``rte_vhost_get_vring_num`` should be used.
 
+   * Few macros are removed in ``rte_virtio_net.h``
+
+     * ``VIRTIO_RXQ``
+     * ``VIRTIO_TXQ``
+     * ``VIRTIO_QNUM``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index dc583e4..891ee70 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -45,6 +45,8 @@
 
 #include "rte_eth_vhost.h"
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 #define ETH_VHOST_IFACE_ARG		"iface"
 #define ETH_VHOST_QUEUES_ARG		"queues"
 #define ETH_VHOST_CLIENT_ARG		"client"
diff --git a/examples/tep_termination/main.h b/examples/tep_termination/main.h
index c0ea766..8ed817d 100644
--- a/examples/tep_termination/main.h
+++ b/examples/tep_termination/main.h
@@ -54,6 +54,8 @@
 /* Max number of devices. Limited by the application. */
 #define MAX_DEVICES 64
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 /* Per-device statistics struct */
 struct device_statistics {
 	uint64_t tx_total;
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 6bb42e8..7a3d251 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -41,6 +41,8 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index f700d2f..1ae1920 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -55,9 +55,6 @@
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
 #define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
 
-/* Enum for virtqueue management. */
-enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
-
 /**
  * Information relating to memory regions including offsets to
  * addresses in QEMUs memory file.
-- 
1.9.0

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

* [PATCH v2 13/22] vhost: do not include net specific headers
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (11 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 14/22] vhost: rename device ops struct Yuanhan Liu
                     ` (9 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Include it internally, at vhost.h.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 7 +++++++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 4 ----
 lib/librte_vhost/vhost.h               | 4 ++++
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 55bf136..2b56e80 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -147,6 +147,13 @@ API Changes
      * ``VIRTIO_TXQ``
      * ``VIRTIO_QNUM``
 
+   * Few net specific header files are removed in ``rte_virtio_net.h``
+
+     * ``linux/virtio_net.h``
+     * ``sys/socket.h``
+     * ``linux/if.h``
+     * ``rte_ether.h``
+
 
 ABI Changes
 -----------
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 7a3d251..ddcd858 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -36,6 +36,8 @@
 
 #include <sys/queue.h>
 
+#include <rte_ether.h>
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 1ae1920..0063949 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -42,14 +42,10 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 #include <linux/virtio_ring.h>
-#include <linux/virtio_net.h>
 #include <sys/eventfd.h>
-#include <sys/socket.h>
-#include <linux/if.h>
 
 #include <rte_memory.h>
 #include <rte_mempool.h>
-#include <rte_ether.h>
 
 #define RTE_VHOST_USER_CLIENT		(1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 84e379a..672098b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -39,8 +39,12 @@
 #include <sys/queue.h>
 #include <unistd.h>
 #include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <sys/socket.h>
+#include <linux/if.h>
 
 #include <rte_log.h>
+#include <rte_ether.h>
 
 #include "rte_virtio_net.h"
 
-- 
1.9.0

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

* [PATCH v2 14/22] vhost: rename device ops struct
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (12 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 13/22] vhost: do not include net specific headers Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
                     ` (8 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rename "virtio_net_device_ops" to "vhost_device_ops", to not let it
be virtio-net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 2 +-
 doc/guides/rel_notes/release_17_05.rst | 3 +++
 drivers/net/vhost/rte_eth_vhost.c      | 2 +-
 examples/tep_termination/main.c        | 2 +-
 examples/vhost/main.c                  | 2 +-
 lib/librte_vhost/Makefile              | 2 +-
 lib/librte_vhost/rte_virtio_net.h      | 4 ++--
 lib/librte_vhost/socket.c              | 6 +++---
 lib/librte_vhost/vhost.h               | 4 ++--
 9 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 40f3b3b..e6e34f3 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 2b56e80..2efe292 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -154,6 +154,9 @@ API Changes
      * ``linux/if.h``
      * ``rte_ether.h``
 
+   * The vhost struct ``virtio_net_device_ops`` is renamed to
+     ``vhost_device_ops``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 891ee70..97a765f 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -671,7 +671,7 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-static struct virtio_net_device_ops vhost_ops = {
+static struct vhost_device_ops vhost_ops = {
 	.new_device          = new_device,
 	.destroy_device      = destroy_device,
 	.vring_state_changed = vring_state_changed,
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 18b977e..738f2d2 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1081,7 +1081,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops = {
+static const struct vhost_device_ops virtio_net_device_ops = {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
 };
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 72a9d69..4395306 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1270,7 +1270,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops =
+static const struct vhost_device_ops virtio_net_device_ops =
 {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 415ffc6..5cf4e93 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -36,7 +36,7 @@ LIB = librte_vhost.a
 
 EXPORT_MAP := rte_vhost_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64
 CFLAGS += -I vhost_user
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 0063949..26ac35f 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -87,7 +87,7 @@ struct rte_vhost_vring {
 /**
  * Device and vring operations.
  */
-struct virtio_net_device_ops {
+struct vhost_device_ops {
 	int (*new_device)(int vid);		/**< Add device. */
 	void (*destroy_device)(int vid);	/**< Remove device. */
 
@@ -198,7 +198,7 @@ static inline uint64_t __attribute__((always_inline))
 
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops);
+	struct vhost_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 8431511..31b868d 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -74,7 +74,7 @@ struct vhost_user_socket {
 	uint64_t supported_features;
 	uint64_t features;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -725,7 +725,7 @@ struct vhost_user_reconnect_list {
  */
 int
 rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops)
+	struct vhost_device_ops const * const ops)
 {
 	struct vhost_user_socket *vsocket;
 
@@ -738,7 +738,7 @@ struct vhost_user_reconnect_list {
 	return vsocket ? 0 : -1;
 }
 
-struct virtio_net_device_ops const *
+struct vhost_device_ops const *
 vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 672098b..225ff2e 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -191,7 +191,7 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
@@ -265,7 +265,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
-struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+struct vhost_device_ops const *vhost_driver_callback_get(const char *path);
 
 /*
  * Backend-specific cleanup.
-- 
1.9.0

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

* [PATCH v2 15/22] vhost: rename virtio-net to vhost
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (13 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 16/22] vhost: add features changed callback Yuanhan Liu
                     ` (7 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "virtio-net" to "vhost" in the API comments and vhost prog guide.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 +++---
 lib/librte_vhost/rte_virtio_net.h   | 14 +++++++-------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index e6e34f3..88f0591 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -130,12 +130,12 @@ The following is an overview of some key Vhost API functions:
 
   * ``new_device(int vid)``
 
-    This callback is invoked when a virtio net device becomes ready. ``vid``
-    is the virtio net device ID.
+    This callback is invoked when a virtio device becomes ready. ``vid``
+    is the vhost device ID.
 
   * ``destroy_device(int vid)``
 
-    This callback is invoked when a virtio net device shuts down (or when the
+    This callback is invoked when a virtio device shuts down (or when the
     vhost connection is broken).
 
   * ``vring_state_changed(int vid, uint16_t queue_id, int enable)``
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 26ac35f..845d0fd 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -222,7 +222,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * is allocated.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The numa node, -1 on failure
@@ -234,11 +234,11 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get the number of queues the device supports.
  *
  * Note this function is deprecated, as it returns a queue pair number,
- * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
  * be used.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The number of queues, 0 on failure
@@ -262,7 +262,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * file path.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param buf
  *  The buffer to stored the queried ifname
  * @param len
@@ -277,7 +277,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get how many avail entries are left in the queue
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index
  *
@@ -292,7 +292,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * count is returned to indicate the number of packets that were succesfully
  * added to the RX queue.
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param pkts
@@ -310,7 +310,7 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
  * construct host mbufs, copies guest buffer content to host mbufs and
  * store them in pkts to be processed.
  * @param vid
- *  virtio-net device
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param mbuf_pool
-- 
1.9.0

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

* [PATCH v2 16/22] vhost: add features changed callback
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (14 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 17/22] vhost: export APIs for live migration support Yuanhan Liu
                     ` (6 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Features could be changed after the feature negotiation. For example,
VHOST_F_LOG_ALL will be set/cleared at the start/end of live migration,
respecitively. Thus, we need a new callback to inform the application
on such change.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 ++++++
 lib/librte_vhost/rte_virtio_net.h   | 10 +++++++++-
 lib/librte_vhost/vhost_user.c       |  5 +++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 88f0591..a4fb1f1 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -143,6 +143,12 @@ The following is an overview of some key Vhost API functions:
     This callback is invoked when a specific queue's state is changed, for
     example to enabled or disabled.
 
+  * ``features_changed(int vid, uint64_t features)``
+
+    This callback is invoked when the features is changed. For example,
+    ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
+    migration, respectively.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 845d0fd..4256927 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -93,7 +93,15 @@ struct vhost_device_ops {
 
 	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
 
-	void *reserved[5]; /**< Reserved for future extension */
+	/**
+	 * Features could be changed after the feature negotiation.
+	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
+	 * start/end of live migration, respectively. This callback
+	 * is used to inform the application on such change.
+	 */
+	int (*features_changed)(int vid, uint64_t features);
+
+	void *reserved[4]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7f93f27..40cc973 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -161,6 +161,11 @@
 	if (features & ~rte_vhost_driver_get_features(dev->ifname))
 		return -1;
 
+	if ((dev->flags & VIRTIO_DEV_RUNNING) && dev->features != features) {
+		if (dev->notify_ops->features_changed)
+			dev->notify_ops->features_changed(dev->vid, features);
+	}
+
 	dev->features = features;
 	if (dev->features &
 		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
-- 
1.9.0

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

* [PATCH v2 17/22] vhost: export APIs for live migration support
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (15 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
                     ` (5 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Export few APIs for the vhost-user driver to log the guest memory writes,
which is a must for live migration support.

This patch basically moves vhost_log_write() and vhost_log_used_vring()
into vhost.h and then add an wrapper (the public API) to them.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  2 ++
 lib/librte_vhost/rte_virtio_net.h      | 43 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 31 ++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 38 ++++++++++++++++++++++++++++++
 lib/librte_vhost/virtio_net.c          | 36 ----------------------------
 5 files changed, 114 insertions(+), 36 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index ff62c39..70c28f7 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -42,5 +42,7 @@ DPDK_17.05 {
 	rte_vhost_get_vhost_vring;
 	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
+	rte_vhost_log_used_vring;
+	rte_vhost_log_write;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 4256927..11b204d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -132,6 +132,49 @@ static inline uint64_t __attribute__((always_inline))
 	return 0;
 }
 
+#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
+
+/**
+ * Log the memory write start with given address.
+ *
+ * This function only need be invoked when the live migration starts.
+ * Therefore, we won't need call it at all in the most of time. For
+ * making the performance impact be minimum, it's suggested to do a
+ * check before calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_write(vid, addr, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param addr
+ *  the starting address for write
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
+
+/**
+ * Log the used ring update start at given offset.
+ *
+ * Same as rte_vhost_log_write, it's suggested to do a check before
+ * calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  the vring index
+ * @param offset
+ *  the offset inside the used ring
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			      uint64_t offset, uint64_t len);
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 74ae3b2..8be5b6a 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -443,3 +443,34 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
+
+void
+rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return;
+
+	vhost_log_write(dev, addr, len);
+}
+
+void
+rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			 uint64_t offset, uint64_t len)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (dev == NULL)
+		return;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return;
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return;
+
+	vhost_log_used_vring(dev, vq, offset, len);
+}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 225ff2e..a199ee6 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -198,6 +198,44 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
+
+#define VHOST_LOG_PAGE	4096
+
+static inline void __attribute__((always_inline))
+vhost_log_page(uint8_t *log_base, uint64_t page)
+{
+	log_base[page / 8] |= 1 << (page % 8);
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
+{
+	uint64_t page;
+
+	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
+		   !dev->log_base || !len))
+		return;
+
+	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
+		return;
+
+	/* To make sure guest memory updates are committed before logging */
+	rte_smp_wmb();
+
+	page = addr / VHOST_LOG_PAGE;
+	while (page * VHOST_LOG_PAGE < addr + len) {
+		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
+		page += 1;
+	}
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
+		     uint64_t offset, uint64_t len)
+{
+	vhost_log_write(dev, vq->log_guest_addr + offset, len);
+}
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 8ed2b93..7ae7904 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -48,42 +48,6 @@
 #include "vhost.h"
 
 #define MAX_PKT_BURST 32
-#define VHOST_LOG_PAGE	4096
-
-static inline void __attribute__((always_inline))
-vhost_log_page(uint8_t *log_base, uint64_t page)
-{
-	log_base[page / 8] |= 1 << (page % 8);
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
-{
-	uint64_t page;
-
-	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
-		   !dev->log_base || !len))
-		return;
-
-	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
-		return;
-
-	/* To make sure guest memory updates are committed before logging */
-	rte_smp_wmb();
-
-	page = addr / VHOST_LOG_PAGE;
-	while (page * VHOST_LOG_PAGE < addr + len) {
-		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
-		page += 1;
-	}
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
-		     uint64_t offset, uint64_t len)
-{
-	vhost_log_write(dev, vq->log_guest_addr + offset, len);
-}
 
 static bool
 is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
-- 
1.9.0

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

* [PATCH v2 18/22] vhost: introduce API to start a specific driver
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (16 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 17/22] vhost: export APIs for live migration support Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 19/22] vhost: rename header file Yuanhan Liu
                     ` (4 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_driver_session_start() to trigger the vhost-user
session. It takes no argument, thus it's a global trigger. And it could
be problematic.

The issue is, currently, rte_vhost_driver_register(path, flags) actually
tries to put it into the session loop (by fdset_add). However, it needs
a set of APIs to set a vhost-user driver properly:
  * rte_vhost_driver_register(path, flags);
  * rte_vhost_driver_set_features(path, features);
  * rte_vhost_driver_callback_register(path, vhost_device_ops);

If a new vhost-user driver is registered after the trigger (think OVS-DPDK
that could add a port dynamically from cmdline), the current code will
effectively starts the session for the new driver just after the first
API rte_vhost_driver_register() is invoked, leaving later calls taking
no effect at all.

To handle the case properly, this patch introduce a new API,
rte_vhost_driver_start(path), to trigger a specific vhost-user driver.
To do that, the rte_vhost_driver_register(path, flags) is simplified
to create the socket only and let rte_vhost_driver_start(path) to
actually put it into the session loop.

Meanwhile, the rte_vhost_driver_session_start is removed: we could hide
the session thread internally (create the thread if it has not been
created). This would also simplify the application.

NOTE: the API order in prog guide is slightly adjusted for showing the
correct invoke order.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 24 +++++------
 doc/guides/rel_notes/release_17_05.rst |  8 ++++
 drivers/net/vhost/rte_eth_vhost.c      | 50 ++-------------------
 examples/tep_termination/main.c        |  8 +++-
 examples/vhost/main.c                  |  9 +++-
 lib/librte_vhost/fd_man.c              |  9 ++--
 lib/librte_vhost/fd_man.h              |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  2 +-
 lib/librte_vhost/rte_virtio_net.h      | 15 ++++++-
 lib/librte_vhost/socket.c              | 79 +++++++++++++++++++---------------
 10 files changed, 104 insertions(+), 102 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index a4fb1f1..5979290 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -116,12 +116,6 @@ The following is an overview of some key Vhost API functions:
   vhost-user driver could be vhost-user net, yet it could be something else,
   say, vhost-user SCSI.
 
-* ``rte_vhost_driver_session_start()``
-
-  This function starts the vhost session loop to handle vhost messages. It
-  starts an infinite loop, therefore it should be called in a dedicated
-  thread.
-
 * ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
@@ -149,6 +143,17 @@ The following is an overview of some key Vhost API functions:
     ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
     migration, respectively.
 
+* ``rte_vhost_driver_disable/enable_features(path, features))``
+
+  This function disables/enables some features. For example, it can be used to
+  disable mergeable buffers and TSO features, which both are enabled by
+  default.
+
+* ``rte_vhost_driver_start(path)``
+
+  This function triggers the vhost-user negotiation. It should be invoked at
+  the end of initializing a vhost-user driver.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
@@ -157,13 +162,6 @@ The following is an overview of some key Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_driver_disable/enable_features(path, features))``
-
-  This function disables/enables some features. For example, it can be used to
-  disable mergeable buffers and TSO features, which both are enabled by
-  default.
-
-
 Vhost-user Implementations
 --------------------------
 
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 2efe292..8f06fc4 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -57,6 +57,11 @@ New Features
   * Enable Vhost PMD's MTU get feature.
   * Get max MTU value from host in Virtio PMD
 
+* **Made the vhost lib be a generic vhost-user lib.**
+
+  Now it could be used to implement any other vhost-user drivers, such
+  as, vhost-user SCSI.
+
 
 Resolved Issues
 ---------------
@@ -157,6 +162,9 @@ API Changes
    * The vhost struct ``virtio_net_device_ops`` is renamed to
      ``vhost_device_ops``
 
+   * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,
+     ``rte_vhost_driver_start`` should be used.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 97a765f..e6c0758 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -127,9 +127,6 @@ struct internal_list {
 
 static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static rte_atomic16_t nb_started_ports;
-static pthread_t session_th;
-
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
 		.link_duplex = ETH_LINK_FULL_DUPLEX,
@@ -743,42 +740,6 @@ struct vhost_xstats_name_off {
 	return vid;
 }
 
-static void *
-vhost_driver_session(void *param __rte_unused)
-{
-	/* start event handling */
-	rte_vhost_driver_session_start();
-
-	return NULL;
-}
-
-static int
-vhost_driver_session_start(void)
-{
-	int ret;
-
-	ret = pthread_create(&session_th,
-			NULL, vhost_driver_session, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't create a thread\n");
-
-	return ret;
-}
-
-static void
-vhost_driver_session_stop(void)
-{
-	int ret;
-
-	ret = pthread_cancel(session_th);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't cancel the thread\n");
-
-	ret = pthread_join(session_th, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't join the thread\n");
-}
-
 static int
 eth_dev_start(struct rte_eth_dev *dev)
 {
@@ -1083,10 +1044,10 @@ struct vhost_xstats_name_off {
 		goto error;
 	}
 
-	/* We need only one message handling thread */
-	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
-		if (vhost_driver_session_start())
-			goto error;
+	if (rte_vhost_driver_start(iface_name) < 0) {
+		RTE_LOG(ERR, PMD, "Failed to start driver for %s\n",
+			iface_name);
+		goto error;
 	}
 
 	return data->port_id;
@@ -1213,9 +1174,6 @@ struct vhost_xstats_name_off {
 
 	eth_dev_close(eth_dev);
 
-	if (rte_atomic16_sub_return(&nb_started_ports, 1) == 0)
-		vhost_driver_session_stop();
-
 	rte_free(vring_states[eth_dev->data->port_id]);
 	vring_states[eth_dev->data->port_id] = NULL;
 
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 738f2d2..24c62cd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1263,7 +1263,13 @@ static inline void __attribute__((always_inline))
 			"failed to register vhost driver callbacks.\n");
 	}
 
-	rte_vhost_driver_session_start();
+	if (rte_vhost_driver_start(dev_basename) < 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to start vhost driver.\n");
+	}
+
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
 
 	return 0;
 }
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4395306..64b3eea 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1545,9 +1545,16 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"failed to register vhost driver callbacks.\n");
 		}
+
+		if (rte_vhost_driver_start(file) < 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to start vhost driver.\n");
+		}
 	}
 
-	rte_vhost_driver_session_start();
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
+
 	return 0;
 
 }
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index c7a4490..2ceacc9 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -210,8 +210,8 @@
  * will wait until the flag is reset to zero(which indicates the callback is
  * finished), then it could free the context after fdset_del.
  */
-void
-fdset_event_dispatch(struct fdset *pfdset)
+void *
+fdset_event_dispatch(void *arg)
 {
 	int i;
 	struct pollfd *pfd;
@@ -221,9 +221,10 @@
 	int fd, numfds;
 	int remove1, remove2;
 	int need_shrink;
+	struct fdset *pfdset = arg;
 
 	if (pfdset == NULL)
-		return;
+		return NULL;
 
 	while (1) {
 
@@ -294,4 +295,6 @@
 		if (need_shrink)
 			fdset_shrink(pfdset);
 	}
+
+	return NULL;
 }
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index d319cac..90d34db 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -64,6 +64,6 @@ int fdset_add(struct fdset *pfdset, int fd,
 
 void *fdset_del(struct fdset *pfdset, int fd);
 
-void fdset_event_dispatch(struct fdset *pfdset);
+void *fdset_event_dispatch(void *arg);
 
 #endif
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 70c28f7..4395fa5 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -4,7 +4,6 @@ DPDK_2.0 {
 	rte_vhost_dequeue_burst;
 	rte_vhost_driver_callback_register;
 	rte_vhost_driver_register;
-	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
 
@@ -35,6 +34,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_driver_start;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 11b204d..627708d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -250,8 +250,19 @@ void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct vhost_device_ops const * const ops);
-/* Start vhost driver session blocking loop. */
-int rte_vhost_driver_session_start(void);
+
+/**
+ *
+ * Start the vhost-user driver.
+ *
+ * This function triggers the vhost-user negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_start(const char *path);
 
 /**
  * Get the MTU value of the device if set in QEMU.
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 31b868d..b056a17 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -58,8 +58,9 @@
  */
 struct vhost_user_socket {
 	char *path;
-	int listenfd;
 	int connfd;
+	struct sockaddr_un un;
+	int socket_fd;
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
@@ -94,7 +95,7 @@ struct vhost_user {
 
 static void vhost_user_server_new_connection(int fd, void *data, int *remove);
 static void vhost_user_read_cb(int fd, void *dat, int *remove);
-static int vhost_user_create_client(struct vhost_user_socket *vsocket);
+static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 
 static struct vhost_user vhost_user = {
 	.fdset = {
@@ -266,22 +267,23 @@ struct vhost_user {
 		free(conn);
 
 		if (vsocket->reconnect)
-			vhost_user_create_client(vsocket);
+			vhost_user_start_client(vsocket);
 	}
 }
 
 static int
-create_unix_socket(const char *path, struct sockaddr_un *un, bool is_server)
+create_unix_socket(struct vhost_user_socket *vsocket)
 {
 	int fd;
+	struct sockaddr_un *un = &vsocket->un;
 
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0)
 		return -1;
 	RTE_LOG(INFO, VHOST_CONFIG, "vhost-user %s: socket created, fd: %d\n",
-		is_server ? "server" : "client", fd);
+		vsocket->is_server ? "server" : "client", fd);
 
-	if (!is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
+	if (!vsocket->is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"vhost-user: can't set nonblocking mode for socket, fd: "
 			"%d (%s)\n", fd, strerror(errno));
@@ -291,25 +293,21 @@ struct vhost_user {
 
 	memset(un, 0, sizeof(*un));
 	un->sun_family = AF_UNIX;
-	strncpy(un->sun_path, path, sizeof(un->sun_path));
+	strncpy(un->sun_path, vsocket->path, sizeof(un->sun_path));
 	un->sun_path[sizeof(un->sun_path) - 1] = '\0';
 
-	return fd;
+	vsocket->socket_fd = fd;
+	return 0;
 }
 
 static int
-vhost_user_create_server(struct vhost_user_socket *vsocket)
+vhost_user_start_server(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = bind(fd, (struct sockaddr *)&un, sizeof(un));
+	ret = bind(fd, (struct sockaddr *)&vsocket->un, sizeof(vsocket->un));
 	if (ret < 0) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to bind to %s: %s; remove it and try again\n",
@@ -322,7 +320,6 @@ struct vhost_user {
 	if (ret < 0)
 		goto err;
 
-	vsocket->listenfd = fd;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
 		  NULL, vsocket);
 	if (ret < 0) {
@@ -441,20 +438,15 @@ struct vhost_user_reconnect_list {
 }
 
 static int
-vhost_user_create_client(struct vhost_user_socket *vsocket)
+vhost_user_start_client(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 	struct vhost_user_reconnect *reconn;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&un,
-					  sizeof(un));
+	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&vsocket->un,
+					  sizeof(vsocket->un));
 	if (ret == 0) {
 		vhost_user_add_connection(fd, vsocket);
 		return 0;
@@ -477,7 +469,7 @@ struct vhost_user_reconnect_list {
 		close(fd);
 		return -1;
 	}
-	reconn->un = un;
+	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
 	pthread_mutex_lock(&reconn_list.mutex);
@@ -627,11 +619,10 @@ struct vhost_user_reconnect_list {
 				goto out;
 			}
 		}
-		ret = vhost_user_create_client(vsocket);
 	} else {
 		vsocket->is_server = true;
-		ret = vhost_user_create_server(vsocket);
 	}
+	ret = create_unix_socket(vsocket);
 	if (ret < 0) {
 		free(vsocket->path);
 		free(vsocket);
@@ -687,8 +678,8 @@ struct vhost_user_reconnect_list {
 
 		if (!strcmp(vsocket->path, path)) {
 			if (vsocket->is_server) {
-				fdset_del(&vhost_user.fdset, vsocket->listenfd);
-				close(vsocket->listenfd);
+				fdset_del(&vhost_user.fdset, vsocket->socket_fd);
+				close(vsocket->socket_fd);
 				unlink(path);
 			} else if (vsocket->reconnect) {
 				vhost_user_remove_reconnect(vsocket);
@@ -751,8 +742,28 @@ struct vhost_device_ops const *
 }
 
 int
-rte_vhost_driver_session_start(void)
+rte_vhost_driver_start(const char *path)
 {
-	fdset_event_dispatch(&vhost_user.fdset);
-	return 0;
+	struct vhost_user_socket *vsocket;
+	static pthread_t fdset_tid;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	if (!vsocket)
+		return -1;
+
+	if (fdset_tid == 0) {
+		int ret = pthread_create(&fdset_tid, NULL, fdset_event_dispatch,
+				     &vhost_user.fdset);
+		if (ret < 0)
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to create fdset handling thread");
+	}
+
+	if (vsocket->is_server)
+		return vhost_user_start_server(vsocket);
+	else
+		return vhost_user_start_client(vsocket);
 }
-- 
1.9.0

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

* [PATCH v2 19/22] vhost: rename header file
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (17 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
                     ` (3 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/rel_notes/deprecation.rst   |   9 -
 doc/guides/rel_notes/release_17_05.rst |   3 +
 drivers/net/vhost/rte_eth_vhost.c      |   2 +-
 drivers/net/vhost/rte_eth_vhost.h      |   2 +-
 examples/tep_termination/main.c        |   2 +-
 examples/tep_termination/vxlan_setup.c |   2 +-
 examples/vhost/main.c                  |   2 +-
 lib/librte_vhost/Makefile              |   2 +-
 lib/librte_vhost/rte_vhost.h           | 421 +++++++++++++++++++++++++++++++++
 lib/librte_vhost/rte_virtio_net.h      | 421 ---------------------------------
 lib/librte_vhost/vhost.c               |   2 +-
 lib/librte_vhost/vhost.h               |   2 +-
 lib/librte_vhost/vhost_user.h          |   2 +-
 lib/librte_vhost/virtio_net.c          |   2 +-
 14 files changed, 434 insertions(+), 440 deletions(-)
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index d6544ed..9708b39 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -95,15 +95,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* vhost: API/ABI changes are planned for 17.05, for making DPDK vhost library
-  generic enough so that applications can build different vhost-user drivers
-  (instead of vhost-user net only) on top of that.
-  Specifically, ``virtio_net_device_ops`` will be renamed to ``vhost_device_ops``.
-  Correspondingly, some API's parameter need be changed. Few more functions also
-  need be reworked to let it be device aware. For example, different virtio device
-  has different feature set, meaning functions like ``rte_vhost_feature_disable``
-  need be changed. Last, file rte_virtio_net.h will be renamed to rte_vhost.h.
-
 * ABI changes are planned for 17.05 in the ``rte_cryptodev_ops`` structure.
   A pointer to a rte_cryptodev_config structure will be added to the
   function prototype ``cryptodev_configure_t``, as a new parameter.
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 8f06fc4..c053fff 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -165,6 +165,9 @@ API Changes
    * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,
      ``rte_vhost_driver_start`` should be used.
 
+   * The vhost public header file ``rte_virtio_net.h`` is renamed to
+     ``rte_vhost.h``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index e6c0758..32e774b 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -40,7 +40,7 @@
 #include <rte_memcpy.h>
 #include <rte_vdev.h>
 #include <rte_kvargs.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_spinlock.h>
 
 #include "rte_eth_vhost.h"
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index ea4bce4..39ca771 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -41,7 +41,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 /*
  * Event description.
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 24c62cd..cd6e3f1 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "main.h"
 #include "vxlan.h"
diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c
index 8f1f15b..87de74d 100644
--- a/examples/tep_termination/vxlan_setup.c
+++ b/examples/tep_termination/vxlan_setup.c
@@ -49,7 +49,7 @@
 #include <rte_tcp.h>
 
 #include "main.h"
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 #include "vxlan.h"
 #include "vxlan_setup.h"
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 64b3eea..08b82f6 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_ip.h>
 #include <rte_tcp.h>
 
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 5cf4e93..4847069 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -51,7 +51,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := fd_man.c socket.c vhost.c vhost_user.c \
 				   virtio_net.c
 
 # install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_vhost.h
 
 # dependencies
 DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_eal
diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
new file mode 100644
index 0000000..d4ee210
--- /dev/null
+++ b/lib/librte_vhost/rte_vhost.h
@@ -0,0 +1,421 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_VHOST_H_
+#define _RTE_VHOST_H_
+
+/**
+ * @file
+ * Interface to vhost-user
+ */
+
+#include <stdint.h>
+#include <linux/vhost.h>
+#include <linux/virtio_ring.h>
+#include <sys/eventfd.h>
+
+#include <rte_memory.h>
+#include <rte_mempool.h>
+
+#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
+#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
+#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
+
+/**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
+/**
+ * Device and vring operations.
+ */
+struct vhost_device_ops {
+	int (*new_device)(int vid);		/**< Add device. */
+	void (*destroy_device)(int vid);	/**< Remove device. */
+
+	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
+
+	/**
+	 * Features could be changed after the feature negotiation.
+	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
+	 * start/end of live migration, respectively. This callback
+	 * is used to inform the application on such change.
+	 */
+	int (*features_changed)(int vid, uint64_t features);
+
+	void *reserved[4]; /**< Reserved for future extension */
+};
+
+/**
+ * Convert guest physical address to host virtual address
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
+#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
+
+/**
+ * Log the memory write start with given address.
+ *
+ * This function only need be invoked when the live migration starts.
+ * Therefore, we won't need call it at all in the most of time. For
+ * making the performance impact be minimum, it's suggested to do a
+ * check before calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_write(vid, addr, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param addr
+ *  the starting address for write
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
+
+/**
+ * Log the used ring update start at given offset.
+ *
+ * Same as rte_vhost_log_write, it's suggested to do a check before
+ * calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  the vring index
+ * @param offset
+ *  the offset inside the used ring
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			      uint64_t offset, uint64_t len);
+
+int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
+
+/**
+ * Register vhost driver. path could be different for multiple
+ * instance support.
+ */
+int rte_vhost_driver_register(const char *path, uint64_t flags);
+
+/* Unregister vhost driver. This is only meaningful to vhost user. */
+int rte_vhost_driver_unregister(const char *path);
+
+/**
+ * Set the feature bits the vhost-user driver supports.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+
+/**
+ * Enable vhost-user driver features.
+ *
+ * Note that
+ * - the param @features should be a subset of the feature bits provided
+ *   by rte_vhost_driver_set_features().
+ * - it must be invoked before vhost-user negotiation starts.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to enable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+
+/**
+ * Disable vhost-user driver features.
+ *
+ * The two notes at rte_vhost_driver_enable_features() also apply here.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to disable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/**
+ * Get the final feature bits for feature negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  Feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_driver_get_features(const char *path);
+
+/**
+ * Get the feature bits after negotiation
+ *
+ * @param vid
+ *  Vhost device ID
+ * @return
+ *  Negotiated feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_get_negotiated_features(int vid);
+
+/* Register callbacks. */
+int rte_vhost_driver_callback_register(const char *path,
+	struct vhost_device_ops const * const ops);
+
+/**
+ *
+ * Start the vhost-user driver.
+ *
+ * This function triggers the vhost-user negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_start(const char *path);
+
+/**
+ * Get the MTU value of the device if set in QEMU.
+ *
+ * @param vid
+ *  virtio-net device ID
+ * @param mtu
+ *  The variable to store the MTU value
+ *
+ * @return
+ *  0: success
+ *  -EAGAIN: device not yet started
+ *  -ENOTSUP: device does not support MTU feature
+ */
+int rte_vhost_get_mtu(int vid, uint16_t *mtu);
+
+/**
+ * Get the numa node from which the virtio net device's memory
+ * is allocated.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The numa node, -1 on failure
+ */
+int rte_vhost_get_numa_node(int vid);
+
+/**
+ * @deprecated
+ * Get the number of queues the device supports.
+ *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of queues, 0 on failure
+ */
+__rte_deprecated
+uint32_t rte_vhost_get_queue_num(int vid);
+
+/**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
+ * Get the virtio net device's ifname, which is the vhost-user socket
+ * file path.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param buf
+ *  The buffer to stored the queried ifname
+ * @param len
+ *  The length of buf
+ *
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_ifname(int vid, char *buf, size_t len);
+
+/**
+ * Get how many avail entries are left in the queue
+ *
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index
+ *
+ * @return
+ *  num of avail entires left
+ */
+uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
+
+/**
+ * This function adds buffers to the virtio devices RX virtqueue. Buffers can
+ * be received from the physical port or from another virtual device. A packet
+ * count is returned to indicate the number of packets that were succesfully
+ * added to the RX queue.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param pkts
+ *  array to contain packets to be enqueued
+ * @param count
+ *  packets num to be enqueued
+ * @return
+ *  num of packets enqueued
+ */
+uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
+	struct rte_mbuf **pkts, uint16_t count);
+
+/**
+ * This function gets guest buffers from the virtio device TX virtqueue,
+ * construct host mbufs, copies guest buffer content to host mbufs and
+ * store them in pkts to be processed.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param mbuf_pool
+ *  mbuf_pool where host mbuf is allocated.
+ * @param pkts
+ *  array to contain packets to be dequeued
+ * @param count
+ *  packets num to be dequeued
+ * @return
+ *  num of packets dequeued
+ */
+uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
+
+/**
+ * Get guest mem table: a list of memory regions.
+ *
+ * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
+ * guest memory regions. Application should free it at destroy_device()
+ * callback.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param mem
+ *  To store the returned mem regions
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
+
+/**
+ * Get guest vring info, including the vring address, vring size, etc.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
+#endif /* _RTE_VHOST_H_ */
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
deleted file mode 100644
index 627708d..0000000
--- a/lib/librte_vhost/rte_virtio_net.h
+++ /dev/null
@@ -1,421 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _VIRTIO_NET_H_
-#define _VIRTIO_NET_H_
-
-/**
- * @file
- * Interface to vhost net
- */
-
-#include <stdint.h>
-#include <linux/vhost.h>
-#include <linux/virtio_ring.h>
-#include <sys/eventfd.h>
-
-#include <rte_memory.h>
-#include <rte_mempool.h>
-
-#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
-#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
-#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
-
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct rte_vhost_mem_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct rte_vhost_memory {
-	uint32_t nregions;
-	struct rte_vhost_mem_region regions[0];
-};
-
-struct rte_vhost_vring {
-	struct vring_desc	*desc;
-	struct vring_avail	*avail;
-	struct vring_used	*used;
-	uint64_t		log_guest_addr;
-
-	int			callfd;
-	int			kickfd;
-	uint16_t		size;
-};
-
-/**
- * Device and vring operations.
- */
-struct vhost_device_ops {
-	int (*new_device)(int vid);		/**< Add device. */
-	void (*destroy_device)(int vid);	/**< Remove device. */
-
-	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
-
-	/**
-	 * Features could be changed after the feature negotiation.
-	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
-	 * start/end of live migration, respectively. This callback
-	 * is used to inform the application on such change.
-	 */
-	int (*features_changed)(int vid, uint64_t features);
-
-	void *reserved[4]; /**< Reserved for future extension */
-};
-
-/**
- * Convert guest physical address to host virtual address
- *
- * @param mem
- *  the guest memory regions
- * @param gpa
- *  the guest physical address for querying
- * @return
- *  the host virtual address on success, 0 on failure
- */
-static inline uint64_t __attribute__((always_inline))
-rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < mem->nregions; i++) {
-		reg = &mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
-#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
-
-/**
- * Log the memory write start with given address.
- *
- * This function only need be invoked when the live migration starts.
- * Therefore, we won't need call it at all in the most of time. For
- * making the performance impact be minimum, it's suggested to do a
- * check before calling it:
- *
- *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
- *                rte_vhost_log_write(vid, addr, len);
- *
- * @param vid
- *  vhost device ID
- * @param addr
- *  the starting address for write
- * @param len
- *  the length to write
- */
-void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
-
-/**
- * Log the used ring update start at given offset.
- *
- * Same as rte_vhost_log_write, it's suggested to do a check before
- * calling it:
- *
- *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
- *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
- *
- * @param vid
- *  vhost device ID
- * @param vring_idx
- *  the vring index
- * @param offset
- *  the offset inside the used ring
- * @param len
- *  the length to write
- */
-void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
-			      uint64_t offset, uint64_t len);
-
-int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
-
-/**
- * Register vhost driver. path could be different for multiple
- * instance support.
- */
-int rte_vhost_driver_register(const char *path, uint64_t flags);
-
-/* Unregister vhost driver. This is only meaningful to vhost user. */
-int rte_vhost_driver_unregister(const char *path);
-
-/**
- * Set the feature bits the vhost-user driver supports.
- *
- * @param path
- *  The vhost-user socket file path
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_set_features(const char *path, uint64_t features);
-
-/**
- * Enable vhost-user driver features.
- *
- * Note that
- * - the param @features should be a subset of the feature bits provided
- *   by rte_vhost_driver_set_features().
- * - it must be invoked before vhost-user negotiation starts.
- *
- * @param path
- *  The vhost-user socket file path
- * @param features
- *  Features to enable
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_enable_features(const char *path, uint64_t features);
-
-/**
- * Disable vhost-user driver features.
- *
- * The two notes at rte_vhost_driver_enable_features() also apply here.
- *
- * @param path
- *  The vhost-user socket file path
- * @param features
- *  Features to disable
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_disable_features(const char *path, uint64_t features);
-
-/**
- * Get the final feature bits for feature negotiation.
- *
- * @param path
- *  The vhost-user socket file path
- * @return
- *  Feature bits on success, 0 on failure
- */
-uint64_t rte_vhost_driver_get_features(const char *path);
-
-/**
- * Get the feature bits after negotiation
- *
- * @param vid
- *  Vhost device ID
- * @return
- *  Negotiated feature bits on success, 0 on failure
- */
-uint64_t rte_vhost_get_negotiated_features(int vid);
-
-/* Register callbacks. */
-int rte_vhost_driver_callback_register(const char *path,
-	struct vhost_device_ops const * const ops);
-
-/**
- *
- * Start the vhost-user driver.
- *
- * This function triggers the vhost-user negotiation.
- *
- * @param path
- *  The vhost-user socket file path
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_start(const char *path);
-
-/**
- * Get the MTU value of the device if set in QEMU.
- *
- * @param vid
- *  virtio-net device ID
- * @param mtu
- *  The variable to store the MTU value
- *
- * @return
- *  0: success
- *  -EAGAIN: device not yet started
- *  -ENOTSUP: device does not support MTU feature
- */
-int rte_vhost_get_mtu(int vid, uint16_t *mtu);
-
-/**
- * Get the numa node from which the virtio net device's memory
- * is allocated.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The numa node, -1 on failure
- */
-int rte_vhost_get_numa_node(int vid);
-
-/**
- * @deprecated
- * Get the number of queues the device supports.
- *
- * Note this function is deprecated, as it returns a queue pair number,
- * which is vhost specific. Instead, rte_vhost_get_vring_num should
- * be used.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of queues, 0 on failure
- */
-__rte_deprecated
-uint32_t rte_vhost_get_queue_num(int vid);
-
-/**
- * Get the number of vrings the device supports.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of vrings, 0 on failure
- */
-uint16_t rte_vhost_get_vring_num(int vid);
-
-/**
- * Get the virtio net device's ifname, which is the vhost-user socket
- * file path.
- *
- * @param vid
- *  vhost device ID
- * @param buf
- *  The buffer to stored the queried ifname
- * @param len
- *  The length of buf
- *
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_ifname(int vid, char *buf, size_t len);
-
-/**
- * Get how many avail entries are left in the queue
- *
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index
- *
- * @return
- *  num of avail entires left
- */
-uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
-
-/**
- * This function adds buffers to the virtio devices RX virtqueue. Buffers can
- * be received from the physical port or from another virtual device. A packet
- * count is returned to indicate the number of packets that were succesfully
- * added to the RX queue.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param pkts
- *  array to contain packets to be enqueued
- * @param count
- *  packets num to be enqueued
- * @return
- *  num of packets enqueued
- */
-uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
-	struct rte_mbuf **pkts, uint16_t count);
-
-/**
- * This function gets guest buffers from the virtio device TX virtqueue,
- * construct host mbufs, copies guest buffer content to host mbufs and
- * store them in pkts to be processed.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param mbuf_pool
- *  mbuf_pool where host mbuf is allocated.
- * @param pkts
- *  array to contain packets to be dequeued
- * @param count
- *  packets num to be dequeued
- * @return
- *  num of packets dequeued
- */
-uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
-	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
-
-/**
- * Get guest mem table: a list of memory regions.
- *
- * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
- * guest memory regions. Application should free it at destroy_device()
- * callback.
- *
- * @param vid
- *  vhost device ID
- * @param mem
- *  To store the returned mem regions
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
-
-/**
- * Get guest vring info, including the vring address, vring size, etc.
- *
- * @param vid
- *  vhost device ID
- * @param vring_idx
- *  vring index
- * @param vring
- *  the structure to hold the requested vring info
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
-			      struct rte_vhost_vring *vring);
-
-#endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 8be5b6a..3105a47 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -45,7 +45,7 @@
 #include <rte_string_fns.h>
 #include <rte_memory.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "vhost.h"
 
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index a199ee6..ddd8a9c 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -46,7 +46,7 @@
 #include <rte_log.h>
 #include <rte_ether.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* Used to indicate that the device is running on a data core */
 #define VIRTIO_DEV_RUNNING 1
diff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h
index 838dec8..2ba22db 100644
--- a/lib/librte_vhost/vhost_user.h
+++ b/lib/librte_vhost/vhost_user.h
@@ -37,7 +37,7 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* refer to hw/virtio/vhost-user.c */
 
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 7ae7904..1004ae6 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -39,7 +39,7 @@
 #include <rte_memcpy.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_sctp.h>
-- 
1.9.0

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

* [PATCH v2 20/22] vhost: workaround the build dependency on mbuf header
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (18 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 19/22] vhost: rename header file Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
                     ` (2 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rte_mbuf struct is something more likely will be used only in vhost-user
net driver, while we have made vhost-user generic enough that it can
be used for implementing other drivers (such as vhost-user SCSI), they
have also include <rte_mbuf.h>. Otherwise, the build will be broken.

We could workaround it by using forward declaration, so that other
non-net drivers won't need include <rte_mbuf.h>.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index d4ee210..bc1a958 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -348,6 +348,8 @@ int rte_vhost_driver_callback_register(const char *path,
  */
 uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
 
+struct rte_mbuf;
+struct rte_mempool;
 /**
  * This function adds buffers to the virtio devices RX virtqueue. Buffers can
  * be received from the physical port or from another virtual device. A packet
-- 
1.9.0

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

* [PATCH v2 21/22] vhost: do not destroy device on repeat mem table message
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (19 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-23  7:10   ` [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

It doesn't make any sense to invoke destroy_device() callback at
while handling SET_MEM_TABLE message.

>From the vhost-user spec, it's the GET_VRING_BASE message indicates
the end of a vhost device: the destroy_device() should be invoked
from there (luckily, we already did that).

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/vhost_user.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 40cc973..079c55e 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -496,12 +496,6 @@
 	uint32_t i;
 	int fd;
 
-	/* Remove from the data plane. */
-	if (dev->flags & VIRTIO_DEV_RUNNING) {
-		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		dev->notify_ops->destroy_device(dev->vid);
-	}
-
 	if (dev->mem) {
 		free_mem_region(dev);
 		rte_free(dev->mem);
-- 
1.9.0

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

* [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (20 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
@ 2017-03-23  7:10   ` Yuanhan Liu
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-23  7:10 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Now DPDK vhost lib has been generic enough, that it can be used to
implement any vhost-user drivers.

For example, this patch implements a very simple vhost-user net driver,
mainly for demonstrating how to use those generic vhost APIs.

And when the --builtin-net-driver option is used, the example virtio-net
driver code will be invoked, instead of the one provided from the vhost
library.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/vhost/Makefile     |   2 +-
 examples/vhost/main.c       |  37 +++-
 examples/vhost/main.h       |  29 +++-
 examples/vhost/virtio_net.c | 405 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 466 insertions(+), 7 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c

diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile
index e95c68a..af7be99 100644
--- a/examples/vhost/Makefile
+++ b/examples/vhost/Makefile
@@ -48,7 +48,7 @@ else
 APP = vhost-switch
 
 # all source are stored in SRCS-y
-SRCS-y := main.c
+SRCS-y := main.c virtio_net.c
 
 CFLAGS += -O2 -D_FILE_OFFSET_BITS=64
 CFLAGS += $(WERROR_FLAGS)
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 08b82f6..022438e 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,6 @@
 #define MBUF_CACHE_SIZE	128
 #define MBUF_DATA_SIZE	RTE_MBUF_DEFAULT_BUF_SIZE
 
-#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
 #define BURST_TX_DRAIN_US 100	/* TX drain every ~100us */
 
 #define BURST_RX_WAIT_US 15	/* Defines how long we wait between retries on RX */
@@ -129,6 +128,8 @@
 static int client_mode;
 static int dequeue_zero_copy;
 
+static int builtin_net_driver;
+
 /* Specify timeout (in useconds) between retries on RX. */
 static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
 /* Specify the number of retries on RX. */
@@ -499,6 +500,7 @@ struct mbuf_table {
 		{"tso", required_argument, NULL, 0},
 		{"client", no_argument, &client_mode, 1},
 		{"dequeue-zero-copy", no_argument, &dequeue_zero_copy, 1},
+		{"builtin-net-driver", no_argument, &builtin_net_driver, 1},
 		{NULL, 0, 0, 0},
 	};
 
@@ -795,7 +797,12 @@ static inline void __attribute__((always_inline))
 {
 	uint16_t ret;
 
-	ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	if (builtin_net_driver) {
+		ret = vs_enqueue_pkts(dst_vdev, VIRTIO_RXQ, &m, 1);
+	} else {
+		ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	}
+
 	if (enable_stats) {
 		rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
 		rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
@@ -1066,8 +1073,13 @@ static inline void __attribute__((always_inline))
 		}
 	}
 
-	enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+	if (builtin_net_driver) {
+		enqueue_count = vs_enqueue_pkts(vdev, VIRTIO_RXQ,
 						pkts, rx_count);
+	} else {
+		enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+						pkts, rx_count);
+	}
 	if (enable_stats) {
 		rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
 		rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
@@ -1083,8 +1095,13 @@ static inline void __attribute__((always_inline))
 	uint16_t count;
 	uint16_t i;
 
-	count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
+	if (builtin_net_driver) {
+		count = vs_dequeue_pkts(vdev, VIRTIO_TXQ, mbuf_pool,
 					pkts, MAX_PKT_BURST);
+	} else {
+		count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ,
+					mbuf_pool, pkts, MAX_PKT_BURST);
+	}
 
 	/* setup VMDq for the first packet */
 	if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
@@ -1187,6 +1204,9 @@ static inline void __attribute__((always_inline))
 		rte_pause();
 	}
 
+	if (builtin_net_driver)
+		vs_vhost_net_remove(vdev);
+
 	TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
 		     lcore_vdev_entry);
 	TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
@@ -1235,6 +1255,9 @@ static inline void __attribute__((always_inline))
 	}
 	vdev->vid = vid;
 
+	if (builtin_net_driver)
+		vs_vhost_net_setup(vdev);
+
 	TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
 	vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
 
@@ -1513,6 +1536,10 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+
+		if (builtin_net_driver)
+			rte_vhost_driver_set_features(file, VIRTIO_NET_FEATURES);
+
 		if (mergeable == 0) {
 			rte_vhost_driver_disable_features(file,
 				1ULL << VIRTIO_NET_F_MRG_RXBUF);
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index ddcd858..5ba7d38 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -43,8 +43,11 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
+#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
@@ -52,6 +55,12 @@ struct device_statistics {
 	rte_atomic64_t	rx_total_atomic;
 };
 
+struct vhost_queue {
+	struct rte_vhost_vring	vr;
+	uint16_t		last_avail_idx;
+	uint16_t		last_used_idx;
+};
+
 struct vhost_dev {
 	/**< Number of memory regions for gpa to hpa translation. */
 	uint32_t nregions_hpa;
@@ -69,9 +78,16 @@ struct vhost_dev {
 	volatile uint8_t remove;
 
 	int vid;
+	uint64_t features;
+	size_t hdr_len;
+	uint16_t nr_vrings;
+	struct rte_vhost_memory *mem;
 	struct device_statistics stats;
 	TAILQ_ENTRY(vhost_dev) global_vdev_entry;
 	TAILQ_ENTRY(vhost_dev) lcore_vdev_entry;
+
+#define MAX_QUEUE_PAIRS	4
+	struct vhost_queue queues[MAX_QUEUE_PAIRS * 2];
 } __rte_cache_aligned;
 
 TAILQ_HEAD(vhost_dev_tailq_list, vhost_dev);
@@ -92,4 +108,15 @@ struct lcore_info {
 	struct vhost_dev_tailq_list vdev_list;
 };
 
+/* we implement non-extra virtio net features */
+#define VIRTIO_NET_FEATURES	0
+
+void vs_vhost_net_setup(struct vhost_dev *dev);
+void vs_vhost_net_remove(struct vhost_dev *dev);
+uint16_t vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mbuf **pkts, uint32_t count);
+
+uint16_t vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mempool *mbuf_pool,
+			 struct rte_mbuf **pkts, uint16_t count);
 #endif /* _MAIN_H_ */
diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c
new file mode 100644
index 0000000..1c53174
--- /dev/null
+++ b/examples/vhost/virtio_net.c
@@ -0,0 +1,405 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <linux/virtio_net.h>
+
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_vhost.h>
+
+#include "main.h"
+
+/*
+ * A very simple vhost-user net driver implementation, without
+ * any extra features being enabled, such as TSO and mrg-Rx.
+ */
+
+void
+vs_vhost_net_setup(struct vhost_dev *dev)
+{
+	uint16_t i;
+	int vid = dev->vid;
+	struct vhost_queue *queue;
+
+	RTE_LOG(INFO, VHOST_CONFIG,
+		"setting builtin vhost-user net driver\n");
+
+	dev->features = rte_vhost_get_negotiated_features(vid);
+	if (dev->features &
+		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
+		dev->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+	} else {
+		dev->hdr_len = sizeof(struct virtio_net_hdr);
+	}
+
+	rte_vhost_get_mem_table(vid, &dev->mem);
+
+	dev->nr_vrings = rte_vhost_get_vring_num(vid);
+	for (i = 0; i < dev->nr_vrings; i++) {
+		queue = &dev->queues[i];
+
+		queue->last_used_idx  = 0;
+		queue->last_avail_idx = 0;
+		rte_vhost_get_vhost_vring(vid, i, &queue->vr);
+	}
+}
+
+void
+vs_vhost_net_remove(struct vhost_dev *dev)
+{
+	free(dev->mem);
+}
+
+static inline int __attribute__((always_inline))
+enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx)
+{
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
+	/* A counter to avoid desc dead loop chain */
+	uint16_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	/*
+	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
+	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
+	 * otherwise stores offset on the stack instead of in a register.
+	 */
+	if (unlikely(desc->len < dev->hdr_len) || !desc_addr)
+		return -1;
+
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	/* write virtio-net header */
+	*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+
+	desc_offset = dev->hdr_len;
+	desc_avail  = desc->len - dev->hdr_len;
+
+	mbuf_avail  = rte_pktmbuf_data_len(m);
+	mbuf_offset = 0;
+	while (mbuf_avail != 0 || m->next != NULL) {
+		/* done with current mbuf, fetch next */
+		if (mbuf_avail == 0) {
+			m = m->next;
+
+			mbuf_offset = 0;
+			mbuf_avail  = rte_pktmbuf_data_len(m);
+		}
+
+		/* done with current desc buf, fetch next */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0) {
+				/* Room in vring buffer is not enough */
+				return -1;
+			}
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+
+			desc = &vr->desc[desc->next];
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
+			rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+	}
+
+	return 0;
+}
+
+uint16_t
+vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+		struct rte_mbuf **pkts, uint32_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint16_t avail_idx, free_entries, start_idx;
+	uint16_t desc_indexes[MAX_PKT_BURST];
+	uint16_t used_idx;
+	uint32_t i;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	avail_idx = *((volatile uint16_t *)&vr->avail->idx);
+	start_idx = queue->last_used_idx;
+	free_entries = avail_idx - start_idx;
+	count = RTE_MIN(count, free_entries);
+	count = RTE_MIN(count, (uint32_t)MAX_PKT_BURST);
+	if (count == 0)
+		return 0;
+
+	/* Retrieve all of the desc indexes first to avoid caching issues. */
+	rte_prefetch0(&vr->avail->ring[start_idx & (vr->size - 1)]);
+	for (i = 0; i < count; i++) {
+		used_idx = (start_idx + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[used_idx];
+		vr->used->ring[used_idx].id = desc_indexes[i];
+		vr->used->ring[used_idx].len = pkts[i]->pkt_len +
+					       dev->hdr_len;
+	}
+
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		uint16_t desc_idx = desc_indexes[i];
+		int err;
+
+		err = enqueue_pkt(dev, vr, pkts[i], desc_idx);
+		if (unlikely(err)) {
+			used_idx = (start_idx + i) & (vr->size - 1);
+			vr->used->ring[used_idx].len = dev->hdr_len;
+		}
+
+		if (i + 1 < count)
+			rte_prefetch0(&vr->desc[desc_indexes[i+1]]);
+	}
+
+	rte_smp_wmb();
+
+	*(volatile uint16_t *)&vr->used->idx += count;
+	queue->last_used_idx += count;
+
+	/* flush used->idx update before we read avail->flags. */
+	rte_mb();
+
+	/* Kick the guest if necessary. */
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+	return count;
+}
+
+static inline int __attribute__((always_inline))
+dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx,
+	    struct rte_mempool *mbuf_pool)
+{
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct rte_mbuf *cur = m, *prev = m;
+	/* A counter to avoid desc dead loop chain */
+	uint32_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	if (unlikely((desc->len < dev->hdr_len)) ||
+			(desc->flags & VRING_DESC_F_INDIRECT))
+		return -1;
+
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+
+	/*
+	 * We don't support ANY_LAYOUT, neither VERSION_1, meaning
+	 * a Tx packet from guest must have 2 desc buffers at least:
+	 * the first for storing the header and the others for
+	 * storing the data.
+	 *
+	 * And since we don't support TSO, we could simply skip the
+	 * header.
+	 */
+	desc = &vr->desc[desc->next];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	desc_offset = 0;
+	desc_avail  = desc->len;
+	nr_desc    += 1;
+
+	mbuf_offset = 0;
+	mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
+	while (1) {
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
+						   mbuf_offset),
+			(void *)((uintptr_t)(desc_addr + desc_offset)),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+
+		/* This desc reaches to its end, get the next one */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0)
+				break;
+
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+			desc = &vr->desc[desc->next];
+
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+			rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		/*
+		 * This mbuf reaches to its end, get a new one
+		 * to hold more data.
+		 */
+		if (mbuf_avail == 0) {
+			cur = rte_pktmbuf_alloc(mbuf_pool);
+			if (unlikely(cur == NULL)) {
+				RTE_LOG(ERR, VHOST_DATA, "Failed to "
+					"allocate memory for mbuf.\n");
+				return -1;
+			}
+
+			prev->next = cur;
+			prev->data_len = mbuf_offset;
+			m->nb_segs += 1;
+			m->pkt_len += mbuf_offset;
+			prev = cur;
+
+			mbuf_offset = 0;
+			mbuf_avail  = cur->buf_len - RTE_PKTMBUF_HEADROOM;
+		}
+	}
+
+	prev->data_len = mbuf_offset;
+	m->pkt_len    += mbuf_offset;
+
+	return 0;
+}
+
+uint16_t
+vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint32_t desc_indexes[MAX_PKT_BURST];
+	uint32_t used_idx;
+	uint32_t i = 0;
+	uint16_t free_entries;
+	uint16_t avail_idx;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	free_entries = *((volatile uint16_t *)&vr->avail->idx) -
+			queue->last_avail_idx;
+	if (free_entries == 0)
+		return 0;
+
+	/* Prefetch available and used ring */
+	avail_idx = queue->last_avail_idx & (vr->size - 1);
+	used_idx  = queue->last_used_idx  & (vr->size - 1);
+	rte_prefetch0(&vr->avail->ring[avail_idx]);
+	rte_prefetch0(&vr->used->ring[used_idx]);
+
+	count = RTE_MIN(count, MAX_PKT_BURST);
+	count = RTE_MIN(count, free_entries);
+
+	/*
+	 * Retrieve all of the head indexes first and pre-update used entries
+	 * to avoid caching issues.
+	 */
+	for (i = 0; i < count; i++) {
+		avail_idx = (queue->last_avail_idx + i) & (vr->size - 1);
+		used_idx  = (queue->last_used_idx  + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[avail_idx];
+
+		vr->used->ring[used_idx].id  = desc_indexes[i];
+		vr->used->ring[used_idx].len = 0;
+	}
+
+	/* Prefetch descriptor index. */
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		int err;
+
+		if (likely(i + 1 < count))
+			rte_prefetch0(&vr->desc[desc_indexes[i + 1]]);
+
+		pkts[i] = rte_pktmbuf_alloc(mbuf_pool);
+		if (unlikely(pkts[i] == NULL)) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed to allocate memory for mbuf.\n");
+			break;
+		}
+
+		err = dequeue_pkt(dev, vr, pkts[i], desc_indexes[i], mbuf_pool);
+		if (unlikely(err)) {
+			rte_pktmbuf_free(pkts[i]);
+			break;
+		}
+
+	}
+	if (!i)
+		return 0;
+
+	queue->last_avail_idx += i;
+	queue->last_used_idx += i;
+	rte_smp_wmb();
+	rte_smp_rmb();
+
+	vr->used->idx += i;
+
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+
+	return i;
+}
-- 
1.9.0

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

* [PATCH v3 00/22] vhost: generic vhost API
  2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
                     ` (21 preceding siblings ...)
  2017-03-23  7:10   ` [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
@ 2017-03-28 12:45   ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
                       ` (22 more replies)
  22 siblings, 23 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

This patchset makes DPDK vhost library generic enough, so that we could
build other vhost-user drivers on top of it. For example, SPDK (Storage
Performance Development Kit) is trying to enable vhost-user SCSI.

The basic idea is, let DPDK vhost be a vhost-user agent. It stores all
the info about the virtio device (i.e. vring address, negotiated features,
etc) and let the specific vhost-user driver to fetch them (by the API
provided by DPDK vhost lib). With those info being provided, the vhost-user
driver then could get/put vring entries, thus, it could exchange data
between the guest and host.

The last patch demonstrates how to use these new APIs to implement a
very simple vhost-user net driver, without any fancy features enabled.


Change log
==========

v2: - rebase
    - updated release note
    - updated API comments
    - renamed rte_vhost_get_vhost_memory to rte_vhost_get_mem_table

    - added a new device callback: features_changed(), bascially for live
      migration support
    - introduced rte_vhost_driver_start() to start a specific driver
    - misc fixes

v3: - rebaseon top of vhost-user socket fix
    - fix reconnect
    - fix shared build
    - fix typos


Major API/ABI Changes summary
=============================

- some renames
  * "struct virtio_net_device_ops" ==> "struct vhost_device_ops"
  * "rte_virtio_net.h"  ==> "rte_vhost.h"

- driver related APIs are bond with the socket file
  * rte_vhost_driver_set_features(socket_file, features);
  * rte_vhost_driver_get_features(socket_file, features);
  * rte_vhost_driver_enable_features(socket_file, features)
  * rte_vhost_driver_disable_features(socket_file, features)
  * rte_vhost_driver_callback_register(socket_file, notify_ops);
  * rte_vhost_driver_start(socket_file);
    This function replaces rte_vhost_driver_session_start(). Check patch
    18 for more information.

- new APIs to fetch guest and vring info
  * rte_vhost_get_mem_table(vid, mem);
  * rte_vhost_get_negotiated_features(vid);
  * rte_vhost_get_vhost_vring(vid, vring_idx, vring);

- new exported structures 
  * struct rte_vhost_vring
  * struct rte_vhost_mem_region
  * struct rte_vhost_memory

- a new device ops callback: features_changed().


Some design choices
===================

While making this patchset, I met quite few design choices and here are
two of them, with the issue and the reason I made such choices provided.
Please let me know if you have any comments (or better ideas).

Export public structures or not
-------------------------------

I made an ABI refactor last time (v16.07): move all the structures
internally and let applications use a "vid" to reference the internal
struct. With that, I hope we could never worry about the annoying ABI
issues.

It works great (and as expected) since then, as far as we only support
virito-net, as far as we can handle all the descs inside vhost lib. It
becomes problematic when a user wants to implement a vhost-user driver
somewhere. For example, it needs do the GPA to VVA translation. Without
any structs exported, some functions like gpa_to_vva() can't be inlined.
Calling it would be costly, especially it's a function we have to invoke
for processing each vring desc.

For that reason, the guest memory regions are exported. With that, the
gpa_to_vva could be inlined.

  
Add helper functions to fetch/update descs or not
-------------------------------------------------

I intended to do it like this way: introduce one function to get @count
of descs from a specific vring and another one to update the used descs.
It's something like
    rte_vhost_vring_get_descs(vid, vring_idx, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vid, vring_idx, count, offset, descs);

With that, vhost-user driver programmer's task would be easier, as he/she
doesn't have to parse the descs any more (such as to handle indirect desc).

But judging that virtio 1.1 is just emerged and it proposes a completely
ring layout, and most importantly, the vring desc structure is also changed,
I'd like to hold the introducation of such two functions. Otherwise, it's
very likely the two will be invalid when virtio 1.1 is out. Though I think
it may could be addressed with a care design, something like making the IOV
generic enough:

	struct rte_vhost_iov {
		uint64_t	gpa;
		uint64_t	vva;
		uint64_t	len;
	};

Instead, I go with the other way: introduce few APIs to export all the vring
infos (vring size, vring addr, callfd, etc), and let the vhost-user driver
read and update the descs. Those info could be passed to vhost-user driver
by introducing one API for each, but for saving few APIs and reducing few
calls for the programmer, I packed few key fields into a new structure, so
that it can be fetched with one call:
        struct rte_vhost_vring {
                struct vring_desc       *desc;
                struct vring_avail      *avail;
                struct vring_used       *used;
                uint64_t                log_guest_addr;
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

When virtio 1.1 comes out, likely a simple change like following would
just work:
        struct rte_vhost_vring {
		union {
			struct {
                		struct vring_desc       *desc;
                		struct vring_avail      *avail;
                		struct vring_used       *used;
                		uint64_t                log_guest_addr;
			};
			struct desc	*desc_1_1;	/* vring addr for virtio 1.1 */
		};
       
                int                     callfd;
                int                     kickfd;
                uint16_t                size;
        };

AFAIK, it's not an ABI breakage. Even if it does, we could introduce a new
API to get the virtio 1.1 ring address.

Those fields are the minimum set I got for a specific vring, with the mind
it would bring the minimum chance to break ABI for future extension. If we
need more info, we could introduce a new API.

OTOH, for getting the best performance, the two functions also have to be
inlined ("vid + vring_idx" combo is replaced with "vring"):
    rte_vhost_vring_get_descs(vring, count, offset, iov, descs);
    rte_vhost_vring_update_used_descs(vring, count, offset, descs);

That said, one way or another, we have to export rte_vhost_vring struct.
For this reason, I didn't rush into introducing the two APIs.

	--yliu


---
Yuanhan Liu (22):
  vhost: introduce driver features related APIs
  net/vhost: remove feature related APIs
  vhost: use new APIs to handle features
  vhost: make notify ops per vhost driver
  vhost: export guest memory regions
  vhost: introduce API to fetch negotiated features
  vhost: export vhost vring info
  vhost: export API to translate gpa to vva
  vhost: turn queue pair to vring
  vhost: export the number of vrings
  vhost: move the device ready check at proper place
  vhost: drop the Rx and Tx queue macro
  vhost: do not include net specific headers
  vhost: rename device ops struct
  vhost: rename virtio-net to vhost
  vhost: add features changed callback
  vhost: export APIs for live migration support
  vhost: introduce API to start a specific driver
  vhost: rename header file
  vhost: workaround the build dependency on mbuf header
  vhost: do not destroy device on repeat mem table message
  examples/vhost: demonstrate the new generic vhost APIs

 doc/guides/prog_guide/vhost_lib.rst         |  42 +--
 doc/guides/rel_notes/deprecation.rst        |   9 -
 doc/guides/rel_notes/release_17_05.rst      |  40 +++
 drivers/net/vhost/rte_eth_vhost.c           | 101 ++-----
 drivers/net/vhost/rte_eth_vhost.h           |  32 +--
 drivers/net/vhost/rte_pmd_vhost_version.map |   3 -
 examples/tep_termination/main.c             |  23 +-
 examples/tep_termination/main.h             |   2 +
 examples/tep_termination/vxlan_setup.c      |   2 +-
 examples/vhost/Makefile                     |   2 +-
 examples/vhost/main.c                       | 100 +++++--
 examples/vhost/main.h                       |  33 ++-
 examples/vhost/virtio_net.c                 | 405 ++++++++++++++++++++++++++
 lib/librte_vhost/Makefile                   |   4 +-
 lib/librte_vhost/fd_man.c                   |   9 +-
 lib/librte_vhost/fd_man.h                   |   2 +-
 lib/librte_vhost/rte_vhost.h                | 423 ++++++++++++++++++++++++++++
 lib/librte_vhost/rte_vhost_version.map      |  16 +-
 lib/librte_vhost/rte_virtio_net.h           | 208 --------------
 lib/librte_vhost/socket.c                   | 227 ++++++++++++---
 lib/librte_vhost/vhost.c                    | 229 ++++++++-------
 lib/librte_vhost/vhost.h                    | 113 +++++---
 lib/librte_vhost/vhost_user.c               | 115 ++++----
 lib/librte_vhost/vhost_user.h               |   2 +-
 lib/librte_vhost/virtio_net.c               |  71 ++---
 25 files changed, 1526 insertions(+), 687 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

-- 
1.9.0

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

* [PATCH v3 01/22] vhost: introduce driver features related APIs
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 02/22] net/vhost: remove feature " Yuanhan Liu
                       ` (21 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Introduce few APIs to set/get/enable/disable driver features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 10 +++-
 lib/librte_vhost/rte_vhost_version.map |  4 ++
 lib/librte_vhost/rte_virtio_net.h      | 51 +++++++++++++++++++
 lib/librte_vhost/socket.c              | 90 ++++++++++++++++++++++++++++++++++
 4 files changed, 153 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index f0862e6..6a4d206 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -53,7 +53,7 @@ vhost library should be able to:
 Vhost API Overview
 ------------------
 
-The following is an overview of the Vhost API functions:
+The following is an overview of some key Vhost API functions:
 
 * ``rte_vhost_driver_register(path, flags)``
 
@@ -110,6 +110,12 @@ The following is an overview of the Vhost API functions:
       of those segments, thus the fewer the segments, the quicker we will get
       the mapping. NOTE: we may speed it by using tree searching in future.
 
+* ``rte_vhost_driver_set_features(path, features)``
+
+  This function sets the feature bits the vhost-user driver supports. The
+  vhost-user driver could be vhost-user net, yet it could be something else,
+  say, vhost-user SCSI.
+
 * ``rte_vhost_driver_session_start()``
 
   This function starts the vhost session loop to handle vhost messages. It
@@ -145,7 +151,7 @@ The following is an overview of the Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_feature_disable/rte_vhost_feature_enable(feature_mask)``
+* ``rte_vhost_driver_disable/enable_features(path, features))``
 
   This function disables/enables some features. For example, it can be used to
   disable mergeable buffers and TSO features, which both are enabled by
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 30b4671..ca6259c 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -34,6 +34,10 @@ DPDK_16.07 {
 DPDK_17.05 {
 	global:
 
+	rte_vhost_driver_disable_features;
+	rte_vhost_driver_enable_features;
+	rte_vhost_driver_get_features;
+	rte_vhost_driver_set_features;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 56829aa..3daf35c 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -94,6 +94,57 @@ struct virtio_net_device_ops {
 /* Unregister vhost driver. This is only meaningful to vhost user. */
 int rte_vhost_driver_unregister(const char *path);
 
+/**
+ * Set the feature bits the vhost-user driver supports.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+
+/**
+ * Enable vhost-user driver features.
+ *
+ * Note that
+ * - the param @features should be a subset of the feature bits provided
+ *   by rte_vhost_driver_set_features().
+ * - it must be invoked before vhost-user negotiation starts.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to enable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+
+/**
+ * Disable vhost-user driver features.
+ *
+ * The two notes at rte_vhost_driver_enable_features() also apply here.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to disable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/**
+ * Get the final feature bits for feature negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  Feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_driver_get_features(const char *path);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
 /* Start vhost driver session blocking loop. */
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 2afde98..e3f3450 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -67,6 +67,16 @@ struct vhost_user_socket {
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
+
+	/*
+	 * The "supported_features" indicates the feature bits the
+	 * vhost driver supports. The "features" indicates the feature
+	 * bits after the rte_vhost_driver_features_disable/enable().
+	 * It is also the final feature bits used for vhost-user
+	 * features negotiation.
+	 */
+	uint64_t supported_features;
+	uint64_t features;
 };
 
 struct vhost_user_connection {
@@ -490,6 +500,86 @@ struct vhost_user_reconnect_list {
 	return 0;
 }
 
+static struct vhost_user_socket *
+find_vhost_user_socket(const char *path)
+{
+	int i;
+
+	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
+		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
+
+		if (!strcmp(vsocket->path, path))
+			return vsocket;
+	}
+
+	return NULL;
+}
+
+int
+rte_vhost_driver_disable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->features &= ~features;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_enable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		if ((vsocket->supported_features & features) != features) {
+			/*
+			 * trying to enable features the driver doesn't
+			 * support.
+			 */
+			pthread_mutex_unlock(&vhost_user.mutex);
+			return -1;
+		}
+		vsocket->features |= features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_set_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		vsocket->supported_features = features;
+		vsocket->features = features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+uint64_t
+rte_vhost_driver_get_features(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->features : (uint64_t)-1;
+}
+
 /*
  * Register a new vhost-user socket; here we could act as server
  * (the default case), or client (when RTE_VHOST_USER_CLIENT) flag
-- 
1.9.0

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

* [PATCH v3 02/22] net/vhost: remove feature related APIs
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 03/22] vhost: use new APIs to handle features Yuanhan Liu
                       ` (20 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The rte_eth_vhost_feature_disable/enable/get APIs are just a wrapper of
rte_vhost_feature_disable/enable/get. However, the later are going to
be refactored; it's going to take an extra parameter (socket_file path),
to let it be per-device.

Instead of changing those vhost-pmd APIs to adapt to the new vhost APIs,
we could simply remove them, and let vdev to serve this purpose. After
all, vdev options is better for disabling/enabling some features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - write more informative commit log on why they are removed.
    - update release note
---
 doc/guides/rel_notes/release_17_05.rst      |  7 +++++++
 drivers/net/vhost/rte_eth_vhost.c           | 25 ------------------------
 drivers/net/vhost/rte_eth_vhost.h           | 30 -----------------------------
 drivers/net/vhost/rte_pmd_vhost_version.map |  3 ---
 4 files changed, 7 insertions(+), 58 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index bb64428..4e405b1 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -129,6 +129,13 @@ API Changes
 * The LPM ``next_hop`` field is extended from 8 bits to 21 bits for IPv6
   while keeping ABI compatibility.
 
+   * The following vhost-pmd APIs are removed
+
+     * ``rte_eth_vhost_feature_disable``
+     * ``rte_eth_vhost_feature_enable``
+     * ``rte_eth_vhost_feature_get``
+
+
 ABI Changes
 -----------
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index a4435da..83063c2 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -965,31 +965,6 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-/**
- * Disable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_disable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_disable(feature_mask);
-}
-
-/**
- * Enable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_enable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_enable(feature_mask);
-}
-
-/* Returns currently supported vhost features */
-uint64_t
-rte_eth_vhost_feature_get(void)
-{
-	return rte_vhost_feature_get();
-}
-
 static const struct eth_dev_ops ops = {
 	.dev_start = eth_dev_start,
 	.dev_stop = eth_dev_stop,
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index 7c98b1a..ea4bce4 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -43,36 +43,6 @@
 
 #include <rte_virtio_net.h>
 
-/**
- * Disable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- * Enable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_enable(uint64_t feature_mask);
-
-/**
- * Returns currently supported vhost features.
- *
- * @return
- *  Vhost features defined in "linux/virtio_net.h".
- */
-uint64_t rte_eth_vhost_feature_get(void);
-
 /*
  * Event description.
  */
diff --git a/drivers/net/vhost/rte_pmd_vhost_version.map b/drivers/net/vhost/rte_pmd_vhost_version.map
index 3d44083..695db85 100644
--- a/drivers/net/vhost/rte_pmd_vhost_version.map
+++ b/drivers/net/vhost/rte_pmd_vhost_version.map
@@ -1,9 +1,6 @@
 DPDK_16.04 {
 	global:
 
-	rte_eth_vhost_feature_disable;
-	rte_eth_vhost_feature_enable;
-	rte_eth_vhost_feature_get;
 	rte_eth_vhost_get_queue_event;
 
 	local: *;
-- 
1.9.0

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

* [PATCH v3 03/22] vhost: use new APIs to handle features
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 02/22] net/vhost: remove feature " Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-29 14:57       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
                       ` (19 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v3: fix comment typo
---
 examples/tep_termination/main.c        |  4 +++-
 examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
 lib/librte_vhost/rte_vhost_version.map |  3 ---
 lib/librte_vhost/rte_virtio_net.h      | 13 ----------
 lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
 lib/librte_vhost/vhost.c               | 42 ---------------------------------
 lib/librte_vhost/vhost.h               | 21 +++++++++++++++++
 lib/librte_vhost/vhost_user.c          |  8 +++----
 8 files changed, 77 insertions(+), 80 deletions(-)

diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 20dafdb..8097dcd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1248,12 +1248,14 @@ static inline void __attribute__((always_inline))
 		rte_eal_remote_launch(switch_worker,
 			mbuf_pool, lcore_id);
 	}
-	rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
 	ret = rte_vhost_driver_register((char *)&dev_basename, 0);
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "failed to register vhost driver.\n");
 
+	rte_vhost_driver_disable_features(dev_basename,
+		1ULL << VIRTIO_NET_F_MRG_RXBUF);
+
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
 
 	rte_vhost_driver_session_start();
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4789947..972a6a8 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -328,16 +328,6 @@ struct mbuf_table {
 
 	if (port >= rte_eth_dev_count()) return -1;
 
-	if (enable_tx_csum == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM);
-
-	if (enable_tso == 0) {
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
-	}
-
 	rx_rings = (uint16_t)dev_info.max_rx_queues;
 	/* Configure ethernet device. */
 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
@@ -531,7 +521,6 @@ struct mbuf_table {
 			vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode =
 				ETH_VMDQ_ACCEPT_BROADCAST |
 				ETH_VMDQ_ACCEPT_MULTICAST;
-			rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX);
 
 			break;
 
@@ -1509,9 +1498,6 @@ static inline void __attribute__((always_inline))
 	RTE_LCORE_FOREACH_SLAVE(lcore_id)
 		rte_eal_remote_launch(switch_worker, NULL, lcore_id);
 
-	if (mergeable == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
-
 	if (client_mode)
 		flags |= RTE_VHOST_USER_CLIENT;
 
@@ -1520,13 +1506,38 @@ static inline void __attribute__((always_inline))
 
 	/* Register vhost user driver to handle vhost messages. */
 	for (i = 0; i < nb_sockets; i++) {
-		ret = rte_vhost_driver_register
-				(socket_files + i * PATH_MAX, flags);
+		char *file = socket_files + i * PATH_MAX;
+		ret = rte_vhost_driver_register(file, flags);
 		if (ret != 0) {
 			unregister_drivers(i);
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+		if (mergeable == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_MRG_RXBUF);
+		}
+
+		if (enable_tx_csum == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_CSUM);
+		}
+
+		if (enable_tso == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO6);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO6);
+		}
+
+		if (promiscuous) {
+			rte_vhost_driver_enable_features(file,
+				1ULL << VIRTIO_NET_F_CTRL_RX);
+		}
 	}
 
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index ca6259c..1150017 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -7,9 +7,6 @@ DPDK_2.0 {
 	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
-	rte_vhost_feature_disable;
-	rte_vhost_feature_enable;
-	rte_vhost_feature_get;
 
 	local: *;
 };
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 3daf35c..5dadd3d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -70,19 +70,6 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
-/**
- *  Disable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- *  Enable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_enable(uint64_t feature_mask);
-
-/* Returns currently supported vhost features */
-uint64_t rte_vhost_feature_get(void);
-
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index e3f3450..87801c0 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -577,7 +577,13 @@ struct vhost_user_reconnect_list {
 	vsocket = find_vhost_user_socket(path);
 	pthread_mutex_unlock(&vhost_user.mutex);
 
-	return vsocket ? vsocket->features : (uint64_t)-1;
+	if (!vsocket) {
+		RTE_LOG(ERR, VHOST_CONFIG,
+			"socket file %s is not registered yet.\n", path);
+		return 0;
+	} else {
+		return vsocket->features;
+	}
 }
 
 /*
@@ -611,6 +617,21 @@ struct vhost_user_reconnect_list {
 	pthread_mutex_init(&vsocket->conn_mutex, NULL);
 	vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
 
+	/*
+	 * Set the supported features correctly for the builtin vhost-user
+	 * net driver.
+	 *
+	 * Applications know nothing about features the builtin virtio net
+	 * driver (virtio_net.c) supports, thus it's not possible for them
+	 * to invoke rte_vhost_driver_set_features(). To workaround it, here
+	 * we set it unconditionally. If the application want to implement
+	 * another vhost-user driver (say SCSI), it should call the
+	 * rte_vhost_driver_set_features(), which will overwrite following
+	 * two values.
+	 */
+	vsocket->supported_features = VIRTIO_NET_SUPPORTED_FEATURES;
+	vsocket->features           = VIRTIO_NET_SUPPORTED_FEATURES;
+
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
 		if (vsocket->reconnect && reconn_tid == 0) {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index dfb08db..7b40a92 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -49,28 +49,6 @@
 
 #include "vhost.h"
 
-#define VHOST_USER_F_PROTOCOL_FEATURES	30
-
-/* Features supported by this lib. */
-#define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
-				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
-				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
-				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
-				(1ULL << VIRTIO_NET_F_MQ)      | \
-				(1ULL << VIRTIO_F_VERSION_1)   | \
-				(1ULL << VHOST_F_LOG_ALL)      | \
-				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
-				(1ULL << VIRTIO_NET_F_CSUM)    | \
-				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
-				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
-				(1ULL << VIRTIO_NET_F_MTU))
-
-uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
-
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
 /* device ops to add/remove device to/from data core. */
@@ -419,26 +397,6 @@ struct virtio_net *
 	return 0;
 }
 
-uint64_t rte_vhost_feature_get(void)
-{
-	return VHOST_FEATURES;
-}
-
-int rte_vhost_feature_disable(uint64_t feature_mask)
-{
-	VHOST_FEATURES = VHOST_FEATURES & ~feature_mask;
-	return 0;
-}
-
-int rte_vhost_feature_enable(uint64_t feature_mask)
-{
-	if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) {
-		VHOST_FEATURES = VHOST_FEATURES | feature_mask;
-		return 0;
-	}
-	return -1;
-}
-
 /*
  * Register ops so that we can add/remove device to data core.
  */
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index daa9328..692691b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -133,6 +133,27 @@ struct vhost_virtqueue {
  #define VIRTIO_F_VERSION_1 32
 #endif
 
+#define VHOST_USER_F_PROTOCOL_FEATURES	30
+
+/* Features supported by this builtin vhost-user net driver. */
+#define VIRTIO_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
+				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
+				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+				(1ULL << VIRTIO_NET_F_MQ)      | \
+				(1ULL << VIRTIO_F_VERSION_1)   | \
+				(1ULL << VHOST_F_LOG_ALL)      | \
+				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
+				(1ULL << VIRTIO_NET_F_CSUM)    | \
+				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
+				(1ULL << VIRTIO_NET_F_MTU))
+
+
 struct guest_page {
 	uint64_t guest_phys_addr;
 	uint64_t host_phys_addr;
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7c6a5f7..d630098 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -147,9 +147,9 @@
  * The features that we support are requested.
  */
 static uint64_t
-vhost_user_get_features(void)
+vhost_user_get_features(struct virtio_net *dev)
 {
-	return VHOST_FEATURES;
+	return rte_vhost_driver_get_features(dev->ifname);
 }
 
 /*
@@ -158,7 +158,7 @@
 static int
 vhost_user_set_features(struct virtio_net *dev, uint64_t features)
 {
-	if (features & ~VHOST_FEATURES)
+	if (features & ~rte_vhost_driver_get_features(dev->ifname))
 		return -1;
 
 	dev->features = features;
@@ -1006,7 +1006,7 @@
 
 	switch (msg.request) {
 	case VHOST_USER_GET_FEATURES:
-		msg.payload.u64 = vhost_user_get_features();
+		msg.payload.u64 = vhost_user_get_features(dev);
 		msg.size = sizeof(msg.payload.u64);
 		send_vhost_message(fd, &msg);
 		break;
-- 
1.9.0

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

* [PATCH v3 04/22] vhost: make notify ops per vhost driver
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (2 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 03/22] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-29 15:03       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 05/22] vhost: export guest memory regions Yuanhan Liu
                       ` (18 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Assume there is an application both support vhost-user net and
vhost-user scsi, the callback should be different. Making notify
ops per vhost driver allow application define different set of
callbacks for different driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v2: - check the return value of callback_register and callback_get
    - update release note
---
 doc/guides/prog_guide/vhost_lib.rst    |  2 +-
 doc/guides/rel_notes/release_17_05.rst |  3 +++
 drivers/net/vhost/rte_eth_vhost.c      | 20 +++++++++++---------
 examples/tep_termination/main.c        |  7 ++++++-
 examples/vhost/main.c                  |  9 +++++++--
 lib/librte_vhost/rte_virtio_net.h      |  3 ++-
 lib/librte_vhost/socket.c              | 32 ++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 16 +---------------
 lib/librte_vhost/vhost.h               |  5 ++++-
 lib/librte_vhost/vhost_user.c          | 22 ++++++++++++++++------
 10 files changed, 83 insertions(+), 36 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 6a4d206..40f3b3b 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 4e405b1..dfa636d 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -135,6 +135,9 @@ API Changes
      * ``rte_eth_vhost_feature_enable``
      * ``rte_eth_vhost_feature_get``
 
+   * The vhost API ``rte_vhost_driver_callback_register(ops)`` takes one
+     more argument: ``rte_vhost_driver_callback_register(path, ops)``.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 83063c2..f6ad616 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -669,6 +669,12 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
+static struct virtio_net_device_ops vhost_ops = {
+	.new_device          = new_device,
+	.destroy_device      = destroy_device,
+	.vring_state_changed = vring_state_changed,
+};
+
 int
 rte_eth_vhost_get_queue_event(uint8_t port_id,
 		struct rte_eth_vhost_queue_event *event)
@@ -738,15 +744,6 @@ struct vhost_xstats_name_off {
 static void *
 vhost_driver_session(void *param __rte_unused)
 {
-	static struct virtio_net_device_ops vhost_ops;
-
-	/* set vhost arguments */
-	vhost_ops.new_device = new_device;
-	vhost_ops.destroy_device = destroy_device;
-	vhost_ops.vring_state_changed = vring_state_changed;
-	if (rte_vhost_driver_callback_register(&vhost_ops) < 0)
-		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
-
 	/* start event handling */
 	rte_vhost_driver_session_start();
 
@@ -1079,6 +1076,11 @@ struct vhost_xstats_name_off {
 	if (rte_vhost_driver_register(iface_name, flags))
 		goto error;
 
+	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
+		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
+		goto error;
+	}
+
 	/* We need only one message handling thread */
 	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
 		if (vhost_driver_session_start())
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 8097dcd..18b977e 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1256,7 +1256,12 @@ static inline void __attribute__((always_inline))
 	rte_vhost_driver_disable_features(dev_basename,
 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+	ret = rte_vhost_driver_callback_register(dev_basename,
+		&virtio_net_device_ops);
+	if (ret != 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to register vhost driver callbacks.\n");
+	}
 
 	rte_vhost_driver_session_start();
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 972a6a8..72a9d69 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1538,9 +1538,14 @@ static inline void __attribute__((always_inline))
 			rte_vhost_driver_enable_features(file,
 				1ULL << VIRTIO_NET_F_CTRL_RX);
 		}
-	}
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+		ret = rte_vhost_driver_callback_register(file,
+			&virtio_net_device_ops);
+		if (ret != 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to register vhost driver callbacks.\n");
+		}
+	}
 
 	rte_vhost_driver_session_start();
 	return 0;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5dadd3d..67bd125 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -133,7 +133,8 @@ struct virtio_net_device_ops {
 uint64_t rte_vhost_driver_get_features(const char *path);
 
 /* Register callbacks. */
-int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
+int rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 87801c0..ed9c5b4 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -77,6 +77,8 @@ struct vhost_user_socket {
 	 */
 	uint64_t supported_features;
 	uint64_t features;
+
+	struct virtio_net_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -741,6 +743,36 @@ struct vhost_user_reconnect_list {
 	return -1;
 }
 
+/*
+ * Register ops so that we can add/remove device to data core.
+ */
+int
+rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->notify_ops = ops;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+struct virtio_net_device_ops const *
+vhost_driver_callback_get(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->notify_ops : NULL;
+}
+
 int
 rte_vhost_driver_session_start(void)
 {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7b40a92..7d7bb3c 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -51,9 +51,6 @@
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* device ops to add/remove device to/from data core. */
-struct virtio_net_device_ops const *notify_ops;
-
 struct virtio_net *
 get_device(int vid)
 {
@@ -253,7 +250,7 @@ struct virtio_net *
 
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(vid);
+		dev->notify_ops->destroy_device(vid);
 	}
 
 	cleanup_device(dev, 1);
@@ -396,14 +393,3 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
-
-/*
- * Register ops so that we can add/remove device to data core.
- */
-int
-rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
-{
-	notify_ops = ops;
-
-	return 0;
-}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 692691b..6186216 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -185,6 +185,8 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
+	struct virtio_net_device_ops const *notify_ops;
+
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
 	struct guest_page       *guest_pages;
@@ -288,7 +290,6 @@ static inline phys_addr_t __attribute__((always_inline))
 	return 0;
 }
 
-struct virtio_net_device_ops const *notify_ops;
 struct virtio_net *get_device(int vid);
 
 int vhost_new_device(void);
@@ -301,6 +302,8 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
+struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+
 /*
  * Backend-specific cleanup.
  *
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index d630098..0cadd79 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -135,7 +135,7 @@
 {
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	cleanup_device(dev, 0);
@@ -503,7 +503,7 @@
 	/* Remove from the data plane. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	if (dev->mem) {
@@ -687,7 +687,7 @@
 						"dequeue zero copy is enabled\n");
 			}
 
-			if (notify_ops->new_device(dev->vid) == 0)
+			if (dev->notify_ops->new_device(dev->vid) == 0)
 				dev->flags |= VIRTIO_DEV_RUNNING;
 		}
 	}
@@ -721,7 +721,7 @@
 	/* We have to stop the queue (virtio) if it is running. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	dev->flags &= ~VIRTIO_DEV_READY;
@@ -763,8 +763,8 @@
 		"set queue enable: %d to qp idx: %d\n",
 		enable, state->index);
 
-	if (notify_ops->vring_state_changed)
-		notify_ops->vring_state_changed(dev->vid, state->index, enable);
+	if (dev->notify_ops->vring_state_changed)
+		dev->notify_ops->vring_state_changed(dev->vid, state->index, enable);
 
 	dev->virtqueue[state->index]->enabled = enable;
 
@@ -978,6 +978,16 @@
 	if (dev == NULL)
 		return -1;
 
+	if (!dev->notify_ops) {
+		dev->notify_ops = vhost_driver_callback_get(dev->ifname);
+		if (!dev->notify_ops) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to get callback ops for driver %s\n",
+				dev->ifname);
+			return -1;
+		}
+	}
+
 	ret = read_vhost_message(fd, &msg);
 	if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
 		if (ret < 0)
-- 
1.9.0

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

* [PATCH v3 05/22] vhost: export guest memory regions
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (3 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
                       ` (17 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Some vhost-user driver may need this info to setup its own page tables
for GPA (guest physical addr) to HPA (host physical addr) translation.
SPDK (Storage Performance Development Kit) is one example.

Besides, by exporting this memory info, we could also export the
gpa_to_vva() as an inline function, which helps for performance.
Otherwise, it has to be referenced indirectly by a "vid".

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 38 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 23 ++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 28 ++-----------------------
 lib/librte_vhost/vhost_user.c          | 12 +++++------
 5 files changed, 70 insertions(+), 32 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 1150017..664a5f3 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -35,6 +35,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 67bd125..5a91f97 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -59,6 +59,28 @@
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
 /**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+/**
  * Device and vring operations.
  */
 struct virtio_net_device_ops {
@@ -244,4 +266,20 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
 uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
 
+/**
+ * Get guest mem table: a list of memory regions.
+ *
+ * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
+ * guest memory regions. Application should free it at destroy_device()
+ * callback.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param mem
+ *  To store the returned mem regions
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7d7bb3c..2b41652 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -359,6 +359,29 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
+{
+	struct virtio_net *dev;
+	struct rte_vhost_memory *m;
+	size_t size;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
+	m = malloc(size);
+	if (!m)
+		return -1;
+
+	m->nregions = dev->mem->nregions;
+	memcpy(m->regions, dev->mem->regions, size);
+	*mem = m;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6186216..6d1986a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -166,7 +166,7 @@ struct guest_page {
  */
 struct virtio_net {
 	/* Frontend (QEMU) memory and memory region information */
-	struct virtio_memory	*mem;
+	struct rte_vhost_memory	*mem;
 	uint64_t		features;
 	uint64_t		protocol_features;
 	int			vid;
@@ -192,30 +192,6 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct virtio_memory_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct virtio_memory {
-	uint32_t nregions;
-	struct virtio_memory_region regions[0];
-};
-
-
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
@@ -255,7 +231,7 @@ struct virtio_memory {
 static inline uint64_t __attribute__((always_inline))
 gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	for (i = 0; i < dev->mem->nregions; i++) {
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 0cadd79..70093a4 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -92,7 +92,7 @@
 free_mem_region(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 
 	if (!dev || !dev->mem)
 		return;
@@ -304,7 +304,7 @@
 static uint64_t
 qva_to_vva(struct virtio_net *dev, uint64_t qva)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	/* Find the region where the address lives. */
@@ -432,7 +432,7 @@
 }
 
 static void
-add_guest_pages(struct virtio_net *dev, struct virtio_memory_region *reg,
+add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 		uint64_t page_size)
 {
 	uint64_t reg_size = reg->size;
@@ -492,7 +492,7 @@
 vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
 	struct VhostUserMemory memory = pmsg->payload.memory;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	void *mmap_addr;
 	uint64_t mmap_size;
 	uint64_t mmap_offset;
@@ -519,8 +519,8 @@
 						sizeof(struct guest_page));
 	}
 
-	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct virtio_memory) +
-		sizeof(struct virtio_memory_region) * memory.nregions, 0);
+	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct rte_vhost_memory) +
+		sizeof(struct rte_vhost_mem_region) * memory.nregions, 0);
 	if (dev->mem == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"(%d) failed to allocate memory for dev->mem\n",
-- 
1.9.0

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

* [PATCH v3 06/22] vhost: introduce API to fetch negotiated features
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (4 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 05/22] vhost: export guest memory regions Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  7:45       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 07/22] vhost: export vhost vring info Yuanhan Liu
                       ` (16 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 10 ++++++++++
 lib/librte_vhost/vhost.c               | 12 ++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 664a5f3..cec1e9e 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -37,5 +37,6 @@ DPDK_17.05 {
 	rte_vhost_driver_set_features;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
+	rte_vhost_get_negotiated_features;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5a91f97..57e57e3 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -154,6 +154,16 @@ struct virtio_net_device_ops {
  */
 uint64_t rte_vhost_driver_get_features(const char *path);
 
+/**
+ * Get the feature bits after negotiation
+ *
+ * @param vid
+ *  Vhost device ID
+ * @return
+ *  Negotiated feature bits on success, 0 on failure
+ */
+uint64_t rte_vhost_get_negotiated_features(int vid);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct virtio_net_device_ops const * const ops);
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 2b41652..08dccfb 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -359,6 +359,18 @@ struct virtio_net *
 	return 0;
 }
 
+uint64_t
+rte_vhost_get_negotiated_features(int vid)
+{
+	struct virtio_net *dev;
+
+	dev = get_device(vid);
+	if (!dev)
+		return 0;
+
+	return dev->features;
+}
+
 int
 rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
 {
-- 
1.9.0

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

* [PATCH v3 07/22] vhost: export vhost vring info
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (5 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  7:48       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
                       ` (15 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v2: - fix off-by-one check
    - add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 26 ++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               |  2 ++
 4 files changed, 59 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index cec1e9e..93b6733 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -38,5 +38,6 @@ DPDK_17.05 {
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
+	rte_vhost_get_vhost_vring;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 57e57e3..5142337 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -80,6 +80,17 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[0];
 };
 
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
 /**
  * Device and vring operations.
  */
@@ -292,4 +303,19 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
  */
 int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
 
+/**
+ * Get guest vring info, including the vring address, vring size, etc.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 08dccfb..6fe613b 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -394,6 +394,36 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			  struct rte_vhost_vring *vring)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return -1;
+
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return -1;
+
+	vring->desc  = vq->desc;
+	vring->avail = vq->avail;
+	vring->used  = vq->used;
+	vring->log_guest_addr  = vq->log_guest_addr;
+
+	vring->callfd  = vq->callfd;
+	vring->kickfd  = vq->kickfd;
+	vring->size    = vq->size;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6d1986a..68ca197 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -120,6 +120,8 @@ struct vhost_virtqueue {
 #ifndef VIRTIO_NET_F_MQ
  #define VIRTIO_NET_F_MQ		22
 #endif
+
+#define VHOST_MAX_VRING			0x100
 #define VHOST_MAX_QUEUE_PAIRS		0x80
 
 #ifndef VIRTIO_NET_F_MTU
-- 
1.9.0

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

* [PATCH v3 08/22] vhost: export API to translate gpa to vva
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (6 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 09/22] vhost: turn queue pair to vring Yuanhan Liu
                       ` (14 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 28 ++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 19 -------------------
 lib/librte_vhost/virtio_net.c          | 23 +++++++++++++----------
 4 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 93b6733..2b309b2 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -39,5 +39,6 @@ DPDK_17.05 {
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 5142337..36674bb 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -103,6 +103,34 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
+/**
+ * Convert guest physical address to host virtual address
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 68ca197..b5c5046 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -229,25 +229,6 @@ struct virtio_net {
 #define MAX_VHOST_DEVICE	1024
 extern struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* Convert guest physical Address to host virtual address */
-static inline uint64_t __attribute__((always_inline))
-gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < dev->mem->nregions; i++) {
-		reg = &dev->mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
 /* Convert guest physical address to host physical address */
 static inline phys_addr_t __attribute__((always_inline))
 gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 337470d..6b9b4c3 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -199,7 +199,7 @@ static inline int __attribute__((always_inline))
 	uint16_t nr_desc = 1;
 
 	desc = &descs[desc_idx];
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	/*
 	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
 	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
@@ -239,7 +239,7 @@ static inline int __attribute__((always_inline))
 				return -1;
 
 			desc = &descs[desc->next];
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -323,7 +323,8 @@ static inline uint32_t __attribute__((always_inline))
 		int err;
 
 		if (vq->desc[desc_idx].flags & VRING_DESC_F_INDIRECT) {
-			descs = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			descs = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_idx].addr);
 			if (unlikely(!descs)) {
 				count = i;
@@ -383,7 +384,7 @@ static inline int __attribute__((always_inline))
 
 	if (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) {
 		descs = (struct vring_desc *)(uintptr_t)
-					gpa_to_vva(dev, vq->desc[idx].addr);
+			rte_vhost_gpa_to_vva(dev->mem, vq->desc[idx].addr);
 		if (unlikely(!descs))
 			return -1;
 
@@ -473,7 +474,7 @@ static inline int __attribute__((always_inline))
 	if (unlikely(m == NULL))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, buf_vec[vec_idx].buf_addr);
 	if (buf_vec[vec_idx].buf_len < dev->vhost_hlen || !desc_addr)
 		return -1;
 
@@ -495,7 +496,8 @@ static inline int __attribute__((always_inline))
 		/* done with current desc buf, get the next one */
 		if (desc_avail == 0) {
 			vec_idx++;
-			desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem,
+					buf_vec[vec_idx].buf_addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -798,7 +800,7 @@ static inline int __attribute__((always_inline))
 			(desc->flags & VRING_DESC_F_INDIRECT))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	if (unlikely(!desc_addr))
 		return -1;
 
@@ -818,7 +820,7 @@ static inline int __attribute__((always_inline))
 		if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 			return -1;
 
-		desc_addr = gpa_to_vva(dev, desc->addr);
+		desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 		if (unlikely(!desc_addr))
 			return -1;
 
@@ -882,7 +884,7 @@ static inline int __attribute__((always_inline))
 			if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 				return -1;
 
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -1113,7 +1115,8 @@ static inline bool __attribute__((always_inline))
 			rte_prefetch0(&vq->desc[desc_indexes[i + 1]]);
 
 		if (vq->desc[desc_indexes[i]].flags & VRING_DESC_F_INDIRECT) {
-			desc = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			desc = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_indexes[i]].addr);
 			if (unlikely(!desc))
 				break;
-- 
1.9.0

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

* [PATCH v3 09/22] vhost: turn queue pair to vring
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (7 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 10/22] vhost: export the number of vrings Yuanhan Liu
                       ` (13 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The queue pair is very virtio-net specific, other devices don't have
such concept. To make it generic, we should log the number of vrings
instead of the number of queue pairs.

This patch just does a simple convert, a later patch would export the
number of vrings to applications.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: enable all vrings by unconditionally
---
 lib/librte_vhost/vhost.c      | 80 +++++++++++++++----------------------------
 lib/librte_vhost/vhost.h      |  4 +--
 lib/librte_vhost/vhost_user.c | 28 +++++----------
 lib/librte_vhost/virtio_net.c | 10 +++---
 4 files changed, 42 insertions(+), 80 deletions(-)

diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 6fe613b..70477c6 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -84,10 +84,8 @@ struct virtio_net *
 
 	vhost_backend_cleanup(dev);
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ], destroy);
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ], destroy);
-	}
+	for (i = 0; i < dev->nr_vring; i++)
+		cleanup_vq(dev->virtqueue[i], destroy);
 }
 
 /*
@@ -97,24 +95,21 @@ struct virtio_net *
 free_device(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct vhost_virtqueue *rxq, *txq;
+	struct vhost_virtqueue *vq;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rxq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		txq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		rte_free(rxq->shadow_used_ring);
-		rte_free(txq->shadow_used_ring);
+		rte_free(vq->shadow_used_ring);
 
-		/* rxq and txq are allocated together as queue-pair */
-		rte_free(rxq);
+		rte_free(vq);
 	}
 
 	rte_free(dev);
 }
 
 static void
-init_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+init_vring_queue(struct vhost_virtqueue *vq)
 {
 	memset(vq, 0, sizeof(struct vhost_virtqueue));
 
@@ -124,69 +119,48 @@ struct virtio_net *
 	/* Backends are set to -1 indicating an inactive device. */
 	vq->backend = -1;
 
-	/* always set the default vq pair to enabled */
-	if (qp_idx == 0)
-		vq->enabled = 1;
+	/*
+	 * always set the vq to enabled; this is to keep compatibility
+	 * with the old QEMU, whereas there is no SET_VRING_ENABLE message.
+	 */
+	vq->enabled = 1;
 
 	TAILQ_INIT(&vq->zmbuf_list);
 }
 
 static void
-init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
-static void
-reset_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+reset_vring_queue(struct vhost_virtqueue *vq)
 {
 	int callfd;
 
 	callfd = vq->callfd;
-	init_vring_queue(vq, qp_idx);
+	init_vring_queue(vq);
 	vq->callfd = callfd;
 }
 
-static void
-reset_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
 int
-alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
+alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {
-	struct vhost_virtqueue *virtqueue = NULL;
-	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
-	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
+	struct vhost_virtqueue *vq;
 
-	virtqueue = rte_malloc(NULL,
-			       sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);
-	if (virtqueue == NULL) {
+	vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
+	if (vq == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
-			"Failed to allocate memory for virt qp:%d.\n", qp_idx);
+			"Failed to allocate memory for vring:%u.\n", vring_idx);
 		return -1;
 	}
 
-	dev->virtqueue[virt_rx_q_idx] = virtqueue;
-	dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
-
-	init_vring_queue_pair(dev, qp_idx);
+	dev->virtqueue[vring_idx] = vq;
+	init_vring_queue(vq);
 
-	dev->virt_qp_nb += 1;
+	dev->nr_vring += 1;
 
 	return 0;
 }
 
 /*
  * Reset some variables in device structure, while keeping few
- * others untouched, such as vid, ifname, virt_qp_nb: they
+ * others untouched, such as vid, ifname, nr_vring: they
  * should be same unless the device is removed.
  */
 void
@@ -198,8 +172,8 @@ struct virtio_net *
 	dev->protocol_features = 0;
 	dev->flags = 0;
 
-	for (i = 0; i < dev->virt_qp_nb; i++)
-		reset_vring_queue_pair(dev, i);
+	for (i = 0; i < dev->nr_vring; i++)
+		reset_vring_queue(dev->virtqueue[i]);
 }
 
 /*
@@ -340,7 +314,7 @@ struct virtio_net *
 	if (dev == NULL)
 		return 0;
 
-	return dev->virt_qp_nb;
+	return dev->nr_vring / 2;
 }
 
 int
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index b5c5046..84e379a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -176,7 +176,7 @@ struct virtio_net {
 	uint16_t		vhost_hlen;
 	/* to tell if we need broadcast rarp packet */
 	rte_atomic16_t		broadcast_rarp;
-	uint32_t		virt_qp_nb;
+	uint32_t		nr_vring;
 	int			dequeue_zero_copy;
 	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
@@ -256,7 +256,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void reset_device(struct virtio_net *dev);
 void vhost_destroy_device(int);
 
-int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
+int alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 70093a4..f841c9b 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -227,13 +227,6 @@
 	struct vhost_virtqueue *old_vq, *vq;
 	int ret;
 
-	/*
-	 * vq is allocated on pairs, we should try to do realloc
-	 * on first queue of one queue pair only.
-	 */
-	if (index % VIRTIO_QNUM != 0)
-		return dev;
-
 	old_dev = dev;
 	vq = old_vq = dev->virtqueue[index];
 
@@ -251,8 +244,7 @@
 	if (oldnode != newnode) {
 		RTE_LOG(INFO, VHOST_CONFIG,
 			"reallocate vq from %d to %d node\n", oldnode, newnode);
-		vq = rte_malloc_socket(NULL, sizeof(*vq) * VIRTIO_QNUM, 0,
-				       newnode);
+		vq = rte_malloc_socket(NULL, sizeof(*vq), 0, newnode);
 		if (!vq)
 			return dev;
 
@@ -284,7 +276,6 @@
 
 out:
 	dev->virtqueue[index] = vq;
-	dev->virtqueue[index + 1] = vq + 1;
 	vhost_devices[dev->vid] = dev;
 
 	return dev;
@@ -615,14 +606,13 @@
 static int
 virtio_is_ready(struct virtio_net *dev)
 {
-	struct vhost_virtqueue *rvq, *tvq;
+	struct vhost_virtqueue *vq;
 	uint32_t i;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		tvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(rvq) || !vq_is_ready(tvq)) {
+		if (!vq_is_ready(vq)) {
 			RTE_LOG(INFO, VHOST_CONFIG,
 				"virtio is not ready for processing.\n");
 			return 0;
@@ -934,7 +924,6 @@
 vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev, VhostUserMsg *msg)
 {
 	uint16_t vring_idx;
-	uint16_t qp_idx;
 
 	switch (msg->request) {
 	case VHOST_USER_SET_VRING_KICK:
@@ -954,17 +943,16 @@
 		return 0;
 	}
 
-	qp_idx = vring_idx / VIRTIO_QNUM;
-	if (qp_idx >= VHOST_MAX_QUEUE_PAIRS) {
+	if (vring_idx >= VHOST_MAX_VRING) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"invalid vring index: %u\n", vring_idx);
 		return -1;
 	}
 
-	if (dev->virtqueue[qp_idx])
+	if (dev->virtqueue[vring_idx])
 		return 0;
 
-	return alloc_vring_queue_pair(dev, qp_idx);
+	return alloc_vring_queue(dev, vring_idx);
 }
 
 int
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 6b9b4c3..8ed2b93 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -86,9 +86,9 @@ static inline void __attribute__((always_inline))
 }
 
 static bool
-is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t qp_nb)
+is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
 {
-	return (is_tx ^ (idx & 1)) == 0 && idx < qp_nb * VIRTIO_QNUM;
+	return (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;
 }
 
 static inline void __attribute__((always_inline))
@@ -283,7 +283,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint32_t i, sz;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -554,7 +554,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint16_t avail_head;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -1019,7 +1019,7 @@ static inline bool __attribute__((always_inline))
 	if (!dev)
 		return 0;
 
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
-- 
1.9.0

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

* [PATCH v3 10/22] vhost: export the number of vrings
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (8 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 11/22] vhost: move the device ready check at proper place Yuanhan Liu
                       ` (12 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_get_queue_num() for telling how many vrings.
However, the return value is the number of "queue pairs", which is
very virtio-net specific. To make it generic, we should return the
number of vrings instead, and let the driver do the proper translation.
Say, virtio-net driver could turn it to the number of queue pairs by
dividing 2.

Meanwhile, mark rte_vhost_get_queue_num as deprecated.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst |  3 +++
 drivers/net/vhost/rte_eth_vhost.c      |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 17 +++++++++++++++++
 lib/librte_vhost/vhost.c               | 11 +++++++++++
 5 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index dfa636d..eca9451 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -138,6 +138,9 @@ API Changes
    * The vhost API ``rte_vhost_driver_callback_register(ops)`` takes one
      more argument: ``rte_vhost_driver_callback_register(path, ops)``.
 
+   * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
+     ``rte_vhost_get_vring_num`` should be used.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index f6ad616..dc583e4 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -569,7 +569,7 @@ struct vhost_xstats_name_off {
 		vq->port = eth_dev->data->port_id;
 	}
 
-	for (i = 0; i < rte_vhost_get_queue_num(vid) * VIRTIO_QNUM; i++)
+	for (i = 0; i < rte_vhost_get_vring_num(vid); i++)
 		rte_vhost_enable_guest_notification(vid, i, 0);
 
 	rte_vhost_get_mtu(vid, &eth_dev->data->mtu);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 2b309b2..8df14dc 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -39,6 +39,7 @@ DPDK_17.05 {
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 36674bb..f700d2f 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -237,17 +237,34 @@ int rte_vhost_driver_callback_register(const char *path,
 int rte_vhost_get_numa_node(int vid);
 
 /**
+ * @deprecated
  * Get the number of queues the device supports.
  *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
  * @param vid
  *  virtio-net device ID
  *
  * @return
  *  The number of queues, 0 on failure
  */
+__rte_deprecated
 uint32_t rte_vhost_get_queue_num(int vid);
 
 /**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
  * Get the virtio net device's ifname, which is the vhost-user socket
  * file path.
  *
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 70477c6..74ae3b2 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -317,6 +317,17 @@ struct virtio_net *
 	return dev->nr_vring / 2;
 }
 
+uint16_t
+rte_vhost_get_vring_num(int vid)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return 0;
+
+	return dev->nr_vring;
+}
+
 int
 rte_vhost_get_ifname(int vid, char *buf, size_t len)
 {
-- 
1.9.0

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

* [PATCH v3 11/22] vhost: move the device ready check at proper place
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (9 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
                       ` (11 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Currently, we check vq->desc, vq->kickfd and vq->callfd to know whether
a virtio device is ready or not. However, we only do it when handling
SET_VRING_KICK message, which could be wrong if a vhost-user frontend
send SET_VRING_KICK first and SET_VRING_CALL later.

To work for all possible vhost-user frontend implementations, we could
move the ready check at the end of vhost-user message handler.

Meanwhile, since we do the check more often than before, the "virtio
not ready" message is dropped, to not flood the screen.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/vhost_user.c | 40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index f841c9b..7f93f27 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -609,14 +609,14 @@
 	struct vhost_virtqueue *vq;
 	uint32_t i;
 
+	if (dev->nr_vring == 0)
+		return 0;
+
 	for (i = 0; i < dev->nr_vring; i++) {
 		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(vq)) {
-			RTE_LOG(INFO, VHOST_CONFIG,
-				"virtio is not ready for processing.\n");
+		if (!vq_is_ready(vq))
 			return 0;
-		}
 	}
 
 	RTE_LOG(INFO, VHOST_CONFIG,
@@ -645,10 +645,6 @@
 	vq->callfd = file.fd;
 }
 
-/*
- *  In vhost-user, when we receive kick message, will test whether virtio
- *  device is ready for packet processing.
- */
 static void
 vhost_user_set_vring_kick(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
@@ -667,20 +663,6 @@
 	if (vq->kickfd >= 0)
 		close(vq->kickfd);
 	vq->kickfd = file.fd;
-
-	if (virtio_is_ready(dev)) {
-		dev->flags |= VIRTIO_DEV_READY;
-
-		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
-			if (dev->dequeue_zero_copy) {
-				RTE_LOG(INFO, VHOST_CONFIG,
-						"dequeue zero copy is enabled\n");
-			}
-
-			if (dev->notify_ops->new_device(dev->vid) == 0)
-				dev->flags |= VIRTIO_DEV_RUNNING;
-		}
-	}
 }
 
 static void
@@ -1102,5 +1084,19 @@
 		send_vhost_message(fd, &msg);
 	}
 
+	if (!(dev->flags & VIRTIO_DEV_RUNNING) && virtio_is_ready(dev)) {
+		dev->flags |= VIRTIO_DEV_READY;
+
+		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
+			if (dev->dequeue_zero_copy) {
+				RTE_LOG(INFO, VHOST_CONFIG,
+						"dequeue zero copy is enabled\n");
+			}
+
+			if (dev->notify_ops->new_device(dev->vid) == 0)
+				dev->flags |= VIRTIO_DEV_RUNNING;
+		}
+	}
+
 	return 0;
 }
-- 
1.9.0

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

* [PATCH v3 12/22] vhost: drop the Rx and Tx queue macro
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (10 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 11/22] vhost: move the device ready check at proper place Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 13/22] vhost: do not include net specific headers Yuanhan Liu
                       ` (10 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

They are virtio-net specific and should be defined inside the virtio-net
driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 6 ++++++
 drivers/net/vhost/rte_eth_vhost.c      | 2 ++
 examples/tep_termination/main.h        | 2 ++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 3 ---
 5 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index eca9451..55bf136 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -141,6 +141,12 @@ API Changes
    * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
      ``rte_vhost_get_vring_num`` should be used.
 
+   * Few macros are removed in ``rte_virtio_net.h``
+
+     * ``VIRTIO_RXQ``
+     * ``VIRTIO_TXQ``
+     * ``VIRTIO_QNUM``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index dc583e4..891ee70 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -45,6 +45,8 @@
 
 #include "rte_eth_vhost.h"
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 #define ETH_VHOST_IFACE_ARG		"iface"
 #define ETH_VHOST_QUEUES_ARG		"queues"
 #define ETH_VHOST_CLIENT_ARG		"client"
diff --git a/examples/tep_termination/main.h b/examples/tep_termination/main.h
index c0ea766..8ed817d 100644
--- a/examples/tep_termination/main.h
+++ b/examples/tep_termination/main.h
@@ -54,6 +54,8 @@
 /* Max number of devices. Limited by the application. */
 #define MAX_DEVICES 64
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 /* Per-device statistics struct */
 struct device_statistics {
 	uint64_t tx_total;
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 6bb42e8..7a3d251 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -41,6 +41,8 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index f700d2f..1ae1920 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -55,9 +55,6 @@
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
 #define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
 
-/* Enum for virtqueue management. */
-enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
-
 /**
  * Information relating to memory regions including offsets to
  * addresses in QEMUs memory file.
-- 
1.9.0

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

* [PATCH v3 13/22] vhost: do not include net specific headers
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (11 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 14/22] vhost: rename device ops struct Yuanhan Liu
                       ` (9 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Include it internally, at vhost.h.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 7 +++++++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 4 ----
 lib/librte_vhost/vhost.h               | 4 ++++
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 55bf136..2b56e80 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -147,6 +147,13 @@ API Changes
      * ``VIRTIO_TXQ``
      * ``VIRTIO_QNUM``
 
+   * Few net specific header files are removed in ``rte_virtio_net.h``
+
+     * ``linux/virtio_net.h``
+     * ``sys/socket.h``
+     * ``linux/if.h``
+     * ``rte_ether.h``
+
 
 ABI Changes
 -----------
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 7a3d251..ddcd858 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -36,6 +36,8 @@
 
 #include <sys/queue.h>
 
+#include <rte_ether.h>
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 1ae1920..0063949 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -42,14 +42,10 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 #include <linux/virtio_ring.h>
-#include <linux/virtio_net.h>
 #include <sys/eventfd.h>
-#include <sys/socket.h>
-#include <linux/if.h>
 
 #include <rte_memory.h>
 #include <rte_mempool.h>
-#include <rte_ether.h>
 
 #define RTE_VHOST_USER_CLIENT		(1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 84e379a..672098b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -39,8 +39,12 @@
 #include <sys/queue.h>
 #include <unistd.h>
 #include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <sys/socket.h>
+#include <linux/if.h>
 
 #include <rte_log.h>
+#include <rte_ether.h>
 
 #include "rte_virtio_net.h"
 
-- 
1.9.0

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

* [PATCH v3 14/22] vhost: rename device ops struct
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (12 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 13/22] vhost: do not include net specific headers Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
                       ` (8 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rename "virtio_net_device_ops" to "vhost_device_ops", to not let it
be virtio-net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 2 +-
 doc/guides/rel_notes/release_17_05.rst | 3 +++
 drivers/net/vhost/rte_eth_vhost.c      | 2 +-
 examples/tep_termination/main.c        | 2 +-
 examples/vhost/main.c                  | 2 +-
 lib/librte_vhost/Makefile              | 2 +-
 lib/librte_vhost/rte_virtio_net.h      | 4 ++--
 lib/librte_vhost/socket.c              | 6 +++---
 lib/librte_vhost/vhost.h               | 4 ++--
 9 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 40f3b3b..e6e34f3 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 2b56e80..2efe292 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -154,6 +154,9 @@ API Changes
      * ``linux/if.h``
      * ``rte_ether.h``
 
+   * The vhost struct ``virtio_net_device_ops`` is renamed to
+     ``vhost_device_ops``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 891ee70..97a765f 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -671,7 +671,7 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-static struct virtio_net_device_ops vhost_ops = {
+static struct vhost_device_ops vhost_ops = {
 	.new_device          = new_device,
 	.destroy_device      = destroy_device,
 	.vring_state_changed = vring_state_changed,
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 18b977e..738f2d2 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1081,7 +1081,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops = {
+static const struct vhost_device_ops virtio_net_device_ops = {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
 };
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 72a9d69..4395306 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1270,7 +1270,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops =
+static const struct vhost_device_ops virtio_net_device_ops =
 {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 415ffc6..5cf4e93 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -36,7 +36,7 @@ LIB = librte_vhost.a
 
 EXPORT_MAP := rte_vhost_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64
 CFLAGS += -I vhost_user
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 0063949..26ac35f 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -87,7 +87,7 @@ struct rte_vhost_vring {
 /**
  * Device and vring operations.
  */
-struct virtio_net_device_ops {
+struct vhost_device_ops {
 	int (*new_device)(int vid);		/**< Add device. */
 	void (*destroy_device)(int vid);	/**< Remove device. */
 
@@ -198,7 +198,7 @@ static inline uint64_t __attribute__((always_inline))
 
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops);
+	struct vhost_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index ed9c5b4..9fb28b5 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -78,7 +78,7 @@ struct vhost_user_socket {
 	uint64_t supported_features;
 	uint64_t features;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -748,7 +748,7 @@ struct vhost_user_reconnect_list {
  */
 int
 rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops)
+	struct vhost_device_ops const * const ops)
 {
 	struct vhost_user_socket *vsocket;
 
@@ -761,7 +761,7 @@ struct vhost_user_reconnect_list {
 	return vsocket ? 0 : -1;
 }
 
-struct virtio_net_device_ops const *
+struct vhost_device_ops const *
 vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 672098b..225ff2e 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -191,7 +191,7 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
@@ -265,7 +265,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
-struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+struct vhost_device_ops const *vhost_driver_callback_get(const char *path);
 
 /*
  * Backend-specific cleanup.
-- 
1.9.0

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

* [PATCH v3 15/22] vhost: rename virtio-net to vhost
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (13 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 16/22] vhost: add features changed callback Yuanhan Liu
                       ` (7 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "virtio-net" to "vhost" in the API comments and vhost prog guide.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 +++---
 lib/librte_vhost/rte_virtio_net.h   | 14 +++++++-------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index e6e34f3..88f0591 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -130,12 +130,12 @@ The following is an overview of some key Vhost API functions:
 
   * ``new_device(int vid)``
 
-    This callback is invoked when a virtio net device becomes ready. ``vid``
-    is the virtio net device ID.
+    This callback is invoked when a virtio device becomes ready. ``vid``
+    is the vhost device ID.
 
   * ``destroy_device(int vid)``
 
-    This callback is invoked when a virtio net device shuts down (or when the
+    This callback is invoked when a virtio device shuts down (or when the
     vhost connection is broken).
 
   * ``vring_state_changed(int vid, uint16_t queue_id, int enable)``
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 26ac35f..845d0fd 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -222,7 +222,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * is allocated.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The numa node, -1 on failure
@@ -234,11 +234,11 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get the number of queues the device supports.
  *
  * Note this function is deprecated, as it returns a queue pair number,
- * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
  * be used.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The number of queues, 0 on failure
@@ -262,7 +262,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * file path.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param buf
  *  The buffer to stored the queried ifname
  * @param len
@@ -277,7 +277,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get how many avail entries are left in the queue
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index
  *
@@ -292,7 +292,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * count is returned to indicate the number of packets that were succesfully
  * added to the RX queue.
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param pkts
@@ -310,7 +310,7 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
  * construct host mbufs, copies guest buffer content to host mbufs and
  * store them in pkts to be processed.
  * @param vid
- *  virtio-net device
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param mbuf_pool
-- 
1.9.0

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

* [PATCH v3 16/22] vhost: add features changed callback
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (14 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  7:50       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 17/22] vhost: export APIs for live migration support Yuanhan Liu
                       ` (6 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Features could be changed after the feature negotiation. For example,
VHOST_F_LOG_ALL will be set/cleared at the start/end of live migration,
respecitively. Thus, we need a new callback to inform the application
on such change.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 ++++++
 lib/librte_vhost/rte_virtio_net.h   | 10 +++++++++-
 lib/librte_vhost/vhost_user.c       |  5 +++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 88f0591..a4fb1f1 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -143,6 +143,12 @@ The following is an overview of some key Vhost API functions:
     This callback is invoked when a specific queue's state is changed, for
     example to enabled or disabled.
 
+  * ``features_changed(int vid, uint64_t features)``
+
+    This callback is invoked when the features is changed. For example,
+    ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
+    migration, respectively.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 845d0fd..4256927 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -93,7 +93,15 @@ struct vhost_device_ops {
 
 	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
 
-	void *reserved[5]; /**< Reserved for future extension */
+	/**
+	 * Features could be changed after the feature negotiation.
+	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
+	 * start/end of live migration, respectively. This callback
+	 * is used to inform the application on such change.
+	 */
+	int (*features_changed)(int vid, uint64_t features);
+
+	void *reserved[4]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7f93f27..40cc973 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -161,6 +161,11 @@
 	if (features & ~rte_vhost_driver_get_features(dev->ifname))
 		return -1;
 
+	if ((dev->flags & VIRTIO_DEV_RUNNING) && dev->features != features) {
+		if (dev->notify_ops->features_changed)
+			dev->notify_ops->features_changed(dev->vid, features);
+	}
+
 	dev->features = features;
 	if (dev->features &
 		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
-- 
1.9.0

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

* [PATCH v3 17/22] vhost: export APIs for live migration support
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (15 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  8:05       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
                       ` (5 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Export few APIs for the vhost-user driver to log the guest memory writes,
which is a must for live migration support.

This patch basically moves vhost_log_write() and vhost_log_used_vring()
into vhost.h and then add an wrapper (the public API) to them.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost_version.map |  2 ++
 lib/librte_vhost/rte_virtio_net.h      | 43 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 31 ++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 38 ++++++++++++++++++++++++++++++
 lib/librte_vhost/virtio_net.c          | 36 ----------------------------
 5 files changed, 114 insertions(+), 36 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 8df14dc..f4b74da 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -41,5 +41,7 @@ DPDK_17.05 {
 	rte_vhost_get_vhost_vring;
 	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
+	rte_vhost_log_used_vring;
+	rte_vhost_log_write;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 4256927..11b204d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -132,6 +132,49 @@ static inline uint64_t __attribute__((always_inline))
 	return 0;
 }
 
+#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
+
+/**
+ * Log the memory write start with given address.
+ *
+ * This function only need be invoked when the live migration starts.
+ * Therefore, we won't need call it at all in the most of time. For
+ * making the performance impact be minimum, it's suggested to do a
+ * check before calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_write(vid, addr, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param addr
+ *  the starting address for write
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
+
+/**
+ * Log the used ring update start at given offset.
+ *
+ * Same as rte_vhost_log_write, it's suggested to do a check before
+ * calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  the vring index
+ * @param offset
+ *  the offset inside the used ring
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			      uint64_t offset, uint64_t len);
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 74ae3b2..8be5b6a 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -443,3 +443,34 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
+
+void
+rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return;
+
+	vhost_log_write(dev, addr, len);
+}
+
+void
+rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			 uint64_t offset, uint64_t len)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (dev == NULL)
+		return;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return;
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return;
+
+	vhost_log_used_vring(dev, vq, offset, len);
+}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 225ff2e..a199ee6 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -198,6 +198,44 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
+
+#define VHOST_LOG_PAGE	4096
+
+static inline void __attribute__((always_inline))
+vhost_log_page(uint8_t *log_base, uint64_t page)
+{
+	log_base[page / 8] |= 1 << (page % 8);
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
+{
+	uint64_t page;
+
+	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
+		   !dev->log_base || !len))
+		return;
+
+	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
+		return;
+
+	/* To make sure guest memory updates are committed before logging */
+	rte_smp_wmb();
+
+	page = addr / VHOST_LOG_PAGE;
+	while (page * VHOST_LOG_PAGE < addr + len) {
+		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
+		page += 1;
+	}
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
+		     uint64_t offset, uint64_t len)
+{
+	vhost_log_write(dev, vq->log_guest_addr + offset, len);
+}
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 8ed2b93..7ae7904 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -48,42 +48,6 @@
 #include "vhost.h"
 
 #define MAX_PKT_BURST 32
-#define VHOST_LOG_PAGE	4096
-
-static inline void __attribute__((always_inline))
-vhost_log_page(uint8_t *log_base, uint64_t page)
-{
-	log_base[page / 8] |= 1 << (page % 8);
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
-{
-	uint64_t page;
-
-	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
-		   !dev->log_base || !len))
-		return;
-
-	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
-		return;
-
-	/* To make sure guest memory updates are committed before logging */
-	rte_smp_wmb();
-
-	page = addr / VHOST_LOG_PAGE;
-	while (page * VHOST_LOG_PAGE < addr + len) {
-		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
-		page += 1;
-	}
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
-		     uint64_t offset, uint64_t len)
-{
-	vhost_log_write(dev, vq->log_guest_addr + offset, len);
-}
 
 static bool
 is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
-- 
1.9.0

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

* [PATCH v3 18/22] vhost: introduce API to start a specific driver
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (16 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 17/22] vhost: export APIs for live migration support Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  9:11       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 19/22] vhost: rename header file Yuanhan Liu
                       ` (4 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_driver_session_start() to trigger the vhost-user
session. It takes no argument, thus it's a global trigger. And it could
be problematic.

The issue is, currently, rte_vhost_driver_register(path, flags) actually
tries to put it into the session loop (by fdset_add). However, it needs
a set of APIs to set a vhost-user driver properly:
  * rte_vhost_driver_register(path, flags);
  * rte_vhost_driver_set_features(path, features);
  * rte_vhost_driver_callback_register(path, vhost_device_ops);

If a new vhost-user driver is registered after the trigger (think OVS-DPDK
that could add a port dynamically from cmdline), the current code will
effectively starts the session for the new driver just after the first
API rte_vhost_driver_register() is invoked, leaving later calls taking
no effect at all.

To handle the case properly, this patch introduce a new API,
rte_vhost_driver_start(path), to trigger a specific vhost-user driver.
To do that, the rte_vhost_driver_register(path, flags) is simplified
to create the socket only and let rte_vhost_driver_start(path) to
actually put it into the session loop.

Meanwhile, the rte_vhost_driver_session_start is removed: we could hide
the session thread internally (create the thread if it has not been
created). This would also simplify the application.

NOTE: the API order in prog guide is slightly adjusted for showing the
correct invoke order.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v3: - fix broken reconnect
---
 doc/guides/prog_guide/vhost_lib.rst    | 24 +++++-----
 doc/guides/rel_notes/release_17_05.rst |  8 ++++
 drivers/net/vhost/rte_eth_vhost.c      | 50 ++------------------
 examples/tep_termination/main.c        |  8 +++-
 examples/vhost/main.c                  |  9 +++-
 lib/librte_vhost/fd_man.c              |  9 ++--
 lib/librte_vhost/fd_man.h              |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  2 +-
 lib/librte_vhost/rte_virtio_net.h      | 15 +++++-
 lib/librte_vhost/socket.c              | 84 ++++++++++++++++++++--------------
 10 files changed, 108 insertions(+), 103 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index a4fb1f1..5979290 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -116,12 +116,6 @@ The following is an overview of some key Vhost API functions:
   vhost-user driver could be vhost-user net, yet it could be something else,
   say, vhost-user SCSI.
 
-* ``rte_vhost_driver_session_start()``
-
-  This function starts the vhost session loop to handle vhost messages. It
-  starts an infinite loop, therefore it should be called in a dedicated
-  thread.
-
 * ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
@@ -149,6 +143,17 @@ The following is an overview of some key Vhost API functions:
     ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
     migration, respectively.
 
+* ``rte_vhost_driver_disable/enable_features(path, features))``
+
+  This function disables/enables some features. For example, it can be used to
+  disable mergeable buffers and TSO features, which both are enabled by
+  default.
+
+* ``rte_vhost_driver_start(path)``
+
+  This function triggers the vhost-user negotiation. It should be invoked at
+  the end of initializing a vhost-user driver.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
@@ -157,13 +162,6 @@ The following is an overview of some key Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_driver_disable/enable_features(path, features))``
-
-  This function disables/enables some features. For example, it can be used to
-  disable mergeable buffers and TSO features, which both are enabled by
-  default.
-
-
 Vhost-user Implementations
 --------------------------
 
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 2efe292..8f06fc4 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -57,6 +57,11 @@ New Features
   * Enable Vhost PMD's MTU get feature.
   * Get max MTU value from host in Virtio PMD
 
+* **Made the vhost lib be a generic vhost-user lib.**
+
+  Now it could be used to implement any other vhost-user drivers, such
+  as, vhost-user SCSI.
+
 
 Resolved Issues
 ---------------
@@ -157,6 +162,9 @@ API Changes
    * The vhost struct ``virtio_net_device_ops`` is renamed to
      ``vhost_device_ops``
 
+   * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,
+     ``rte_vhost_driver_start`` should be used.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 97a765f..e6c0758 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -127,9 +127,6 @@ struct internal_list {
 
 static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static rte_atomic16_t nb_started_ports;
-static pthread_t session_th;
-
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
 		.link_duplex = ETH_LINK_FULL_DUPLEX,
@@ -743,42 +740,6 @@ struct vhost_xstats_name_off {
 	return vid;
 }
 
-static void *
-vhost_driver_session(void *param __rte_unused)
-{
-	/* start event handling */
-	rte_vhost_driver_session_start();
-
-	return NULL;
-}
-
-static int
-vhost_driver_session_start(void)
-{
-	int ret;
-
-	ret = pthread_create(&session_th,
-			NULL, vhost_driver_session, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't create a thread\n");
-
-	return ret;
-}
-
-static void
-vhost_driver_session_stop(void)
-{
-	int ret;
-
-	ret = pthread_cancel(session_th);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't cancel the thread\n");
-
-	ret = pthread_join(session_th, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't join the thread\n");
-}
-
 static int
 eth_dev_start(struct rte_eth_dev *dev)
 {
@@ -1083,10 +1044,10 @@ struct vhost_xstats_name_off {
 		goto error;
 	}
 
-	/* We need only one message handling thread */
-	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
-		if (vhost_driver_session_start())
-			goto error;
+	if (rte_vhost_driver_start(iface_name) < 0) {
+		RTE_LOG(ERR, PMD, "Failed to start driver for %s\n",
+			iface_name);
+		goto error;
 	}
 
 	return data->port_id;
@@ -1213,9 +1174,6 @@ struct vhost_xstats_name_off {
 
 	eth_dev_close(eth_dev);
 
-	if (rte_atomic16_sub_return(&nb_started_ports, 1) == 0)
-		vhost_driver_session_stop();
-
 	rte_free(vring_states[eth_dev->data->port_id]);
 	vring_states[eth_dev->data->port_id] = NULL;
 
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 738f2d2..24c62cd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1263,7 +1263,13 @@ static inline void __attribute__((always_inline))
 			"failed to register vhost driver callbacks.\n");
 	}
 
-	rte_vhost_driver_session_start();
+	if (rte_vhost_driver_start(dev_basename) < 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to start vhost driver.\n");
+	}
+
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
 
 	return 0;
 }
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4395306..64b3eea 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1545,9 +1545,16 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"failed to register vhost driver callbacks.\n");
 		}
+
+		if (rte_vhost_driver_start(file) < 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to start vhost driver.\n");
+		}
 	}
 
-	rte_vhost_driver_session_start();
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
+
 	return 0;
 
 }
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index c7a4490..2ceacc9 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -210,8 +210,8 @@
  * will wait until the flag is reset to zero(which indicates the callback is
  * finished), then it could free the context after fdset_del.
  */
-void
-fdset_event_dispatch(struct fdset *pfdset)
+void *
+fdset_event_dispatch(void *arg)
 {
 	int i;
 	struct pollfd *pfd;
@@ -221,9 +221,10 @@
 	int fd, numfds;
 	int remove1, remove2;
 	int need_shrink;
+	struct fdset *pfdset = arg;
 
 	if (pfdset == NULL)
-		return;
+		return NULL;
 
 	while (1) {
 
@@ -294,4 +295,6 @@
 		if (need_shrink)
 			fdset_shrink(pfdset);
 	}
+
+	return NULL;
 }
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index d319cac..90d34db 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -64,6 +64,6 @@ int fdset_add(struct fdset *pfdset, int fd,
 
 void *fdset_del(struct fdset *pfdset, int fd);
 
-void fdset_event_dispatch(struct fdset *pfdset);
+void *fdset_event_dispatch(void *arg);
 
 #endif
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index f4b74da..0785873 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -4,7 +4,6 @@ DPDK_2.0 {
 	rte_vhost_dequeue_burst;
 	rte_vhost_driver_callback_register;
 	rte_vhost_driver_register;
-	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
 
@@ -35,6 +34,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_driver_start;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 11b204d..627708d 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -250,8 +250,19 @@ void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct vhost_device_ops const * const ops);
-/* Start vhost driver session blocking loop. */
-int rte_vhost_driver_session_start(void);
+
+/**
+ *
+ * Start the vhost-user driver.
+ *
+ * This function triggers the vhost-user negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_start(const char *path);
 
 /**
  * Get the MTU value of the device if set in QEMU.
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 9fb28b5..eb2aedd 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -63,7 +63,8 @@ struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
 	pthread_mutex_t conn_mutex;
 	char *path;
-	int listenfd;
+	int socket_fd;
+	struct sockaddr_un un;
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
@@ -101,7 +102,8 @@ struct vhost_user {
 
 static void vhost_user_server_new_connection(int fd, void *data, int *remove);
 static void vhost_user_read_cb(int fd, void *dat, int *remove);
-static int vhost_user_create_client(struct vhost_user_socket *vsocket);
+static int create_unix_socket(struct vhost_user_socket *vsocket);
+static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 
 static struct vhost_user vhost_user = {
 	.fdset = {
@@ -280,23 +282,26 @@ struct vhost_user {
 
 		free(conn);
 
-		if (vsocket->reconnect)
-			vhost_user_create_client(vsocket);
+		if (vsocket->reconnect) {
+			create_unix_socket(vsocket);
+			vhost_user_start_client(vsocket);
+		}
 	}
 }
 
 static int
-create_unix_socket(const char *path, struct sockaddr_un *un, bool is_server)
+create_unix_socket(struct vhost_user_socket *vsocket)
 {
 	int fd;
+	struct sockaddr_un *un = &vsocket->un;
 
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0)
 		return -1;
 	RTE_LOG(INFO, VHOST_CONFIG, "vhost-user %s: socket created, fd: %d\n",
-		is_server ? "server" : "client", fd);
+		vsocket->is_server ? "server" : "client", fd);
 
-	if (!is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
+	if (!vsocket->is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"vhost-user: can't set nonblocking mode for socket, fd: "
 			"%d (%s)\n", fd, strerror(errno));
@@ -306,25 +311,21 @@ struct vhost_user {
 
 	memset(un, 0, sizeof(*un));
 	un->sun_family = AF_UNIX;
-	strncpy(un->sun_path, path, sizeof(un->sun_path));
+	strncpy(un->sun_path, vsocket->path, sizeof(un->sun_path));
 	un->sun_path[sizeof(un->sun_path) - 1] = '\0';
 
-	return fd;
+	vsocket->socket_fd = fd;
+	return 0;
 }
 
 static int
-vhost_user_create_server(struct vhost_user_socket *vsocket)
+vhost_user_start_server(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = bind(fd, (struct sockaddr *)&un, sizeof(un));
+	ret = bind(fd, (struct sockaddr *)&vsocket->un, sizeof(vsocket->un));
 	if (ret < 0) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to bind to %s: %s; remove it and try again\n",
@@ -337,7 +338,6 @@ struct vhost_user {
 	if (ret < 0)
 		goto err;
 
-	vsocket->listenfd = fd;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
 		  NULL, vsocket);
 	if (ret < 0) {
@@ -456,20 +456,15 @@ struct vhost_user_reconnect_list {
 }
 
 static int
-vhost_user_create_client(struct vhost_user_socket *vsocket)
+vhost_user_start_client(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 	struct vhost_user_reconnect *reconn;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&un,
-					  sizeof(un));
+	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&vsocket->un,
+					  sizeof(vsocket->un));
 	if (ret == 0) {
 		vhost_user_add_connection(fd, vsocket);
 		return 0;
@@ -492,7 +487,7 @@ struct vhost_user_reconnect_list {
 		close(fd);
 		return -1;
 	}
-	reconn->un = un;
+	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
 	pthread_mutex_lock(&reconn_list.mutex);
@@ -643,11 +638,10 @@ struct vhost_user_reconnect_list {
 				goto out;
 			}
 		}
-		ret = vhost_user_create_client(vsocket);
 	} else {
 		vsocket->is_server = true;
-		ret = vhost_user_create_server(vsocket);
 	}
+	ret = create_unix_socket(vsocket);
 	if (ret < 0) {
 		free(vsocket->path);
 		free(vsocket);
@@ -703,8 +697,8 @@ struct vhost_user_reconnect_list {
 
 		if (!strcmp(vsocket->path, path)) {
 			if (vsocket->is_server) {
-				fdset_del(&vhost_user.fdset, vsocket->listenfd);
-				close(vsocket->listenfd);
+				fdset_del(&vhost_user.fdset, vsocket->socket_fd);
+				close(vsocket->socket_fd);
 				unlink(path);
 			} else if (vsocket->reconnect) {
 				vhost_user_remove_reconnect(vsocket);
@@ -774,8 +768,28 @@ struct vhost_device_ops const *
 }
 
 int
-rte_vhost_driver_session_start(void)
+rte_vhost_driver_start(const char *path)
 {
-	fdset_event_dispatch(&vhost_user.fdset);
-	return 0;
+	struct vhost_user_socket *vsocket;
+	static pthread_t fdset_tid;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	if (!vsocket)
+		return -1;
+
+	if (fdset_tid == 0) {
+		int ret = pthread_create(&fdset_tid, NULL, fdset_event_dispatch,
+				     &vhost_user.fdset);
+		if (ret < 0)
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to create fdset handling thread");
+	}
+
+	if (vsocket->is_server)
+		return vhost_user_start_server(vsocket);
+	else
+		return vhost_user_start_client(vsocket);
 }
-- 
1.9.0

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

* [PATCH v3 19/22] vhost: rename header file
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (17 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-28 12:45     ` [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
                       ` (3 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/rel_notes/deprecation.rst               |  9 ---------
 doc/guides/rel_notes/release_17_05.rst             |  3 +++
 drivers/net/vhost/rte_eth_vhost.c                  |  2 +-
 drivers/net/vhost/rte_eth_vhost.h                  |  2 +-
 examples/tep_termination/main.c                    |  2 +-
 examples/tep_termination/vxlan_setup.c             |  2 +-
 examples/vhost/main.c                              |  2 +-
 lib/librte_vhost/Makefile                          |  2 +-
 lib/librte_vhost/{rte_virtio_net.h => rte_vhost.h} | 10 +++++-----
 lib/librte_vhost/vhost.c                           |  2 +-
 lib/librte_vhost/vhost.h                           |  2 +-
 lib/librte_vhost/vhost_user.h                      |  2 +-
 lib/librte_vhost/virtio_net.c                      |  2 +-
 13 files changed, 18 insertions(+), 24 deletions(-)
 rename lib/librte_vhost/{rte_virtio_net.h => rte_vhost.h} (98%)

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index d6544ed..9708b39 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -95,15 +95,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* vhost: API/ABI changes are planned for 17.05, for making DPDK vhost library
-  generic enough so that applications can build different vhost-user drivers
-  (instead of vhost-user net only) on top of that.
-  Specifically, ``virtio_net_device_ops`` will be renamed to ``vhost_device_ops``.
-  Correspondingly, some API's parameter need be changed. Few more functions also
-  need be reworked to let it be device aware. For example, different virtio device
-  has different feature set, meaning functions like ``rte_vhost_feature_disable``
-  need be changed. Last, file rte_virtio_net.h will be renamed to rte_vhost.h.
-
 * ABI changes are planned for 17.05 in the ``rte_cryptodev_ops`` structure.
   A pointer to a rte_cryptodev_config structure will be added to the
   function prototype ``cryptodev_configure_t``, as a new parameter.
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 8f06fc4..c053fff 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -165,6 +165,9 @@ API Changes
    * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,
      ``rte_vhost_driver_start`` should be used.
 
+   * The vhost public header file ``rte_virtio_net.h`` is renamed to
+     ``rte_vhost.h``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index e6c0758..32e774b 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -40,7 +40,7 @@
 #include <rte_memcpy.h>
 #include <rte_vdev.h>
 #include <rte_kvargs.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_spinlock.h>
 
 #include "rte_eth_vhost.h"
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index ea4bce4..39ca771 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -41,7 +41,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 /*
  * Event description.
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 24c62cd..cd6e3f1 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "main.h"
 #include "vxlan.h"
diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c
index 8f1f15b..87de74d 100644
--- a/examples/tep_termination/vxlan_setup.c
+++ b/examples/tep_termination/vxlan_setup.c
@@ -49,7 +49,7 @@
 #include <rte_tcp.h>
 
 #include "main.h"
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 #include "vxlan.h"
 #include "vxlan_setup.h"
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 64b3eea..08b82f6 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_ip.h>
 #include <rte_tcp.h>
 
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 5cf4e93..4847069 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -51,7 +51,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := fd_man.c socket.c vhost.c vhost_user.c \
 				   virtio_net.c
 
 # install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_vhost.h
 
 # dependencies
 DEPDIRS-$(CONFIG_RTE_LIBRTE_VHOST) += lib/librte_eal
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_vhost.h
similarity index 98%
rename from lib/librte_vhost/rte_virtio_net.h
rename to lib/librte_vhost/rte_vhost.h
index 627708d..d4ee210 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -31,12 +31,12 @@
  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef _VIRTIO_NET_H_
-#define _VIRTIO_NET_H_
+#ifndef _RTE_VHOST_H_
+#define _RTE_VHOST_H_
 
 /**
  * @file
- * Interface to vhost net
+ * Interface to vhost-user
  */
 
 #include <stdint.h>
@@ -418,4 +418,4 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
 			      struct rte_vhost_vring *vring);
 
-#endif /* _VIRTIO_NET_H_ */
+#endif /* _RTE_VHOST_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 8be5b6a..3105a47 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -45,7 +45,7 @@
 #include <rte_string_fns.h>
 #include <rte_memory.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "vhost.h"
 
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index a199ee6..ddd8a9c 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -46,7 +46,7 @@
 #include <rte_log.h>
 #include <rte_ether.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* Used to indicate that the device is running on a data core */
 #define VIRTIO_DEV_RUNNING 1
diff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h
index 838dec8..2ba22db 100644
--- a/lib/librte_vhost/vhost_user.h
+++ b/lib/librte_vhost/vhost_user.h
@@ -37,7 +37,7 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* refer to hw/virtio/vhost-user.c */
 
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 7ae7904..1004ae6 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -39,7 +39,7 @@
 #include <rte_memcpy.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_sctp.h>
-- 
1.9.0

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

* [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (18 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 19/22] vhost: rename header file Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  9:13       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
                       ` (2 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rte_mbuf struct is something more likely will be used only in vhost-user
net driver, while we have made vhost-user generic enough that it can
be used for implementing other drivers (such as vhost-user SCSI), they
have also include <rte_mbuf.h>. Otherwise, the build will be broken.

We could workaround it by using forward declaration, so that other
non-net drivers won't need include <rte_mbuf.h>.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/rte_vhost.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index d4ee210..bc1a958 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -348,6 +348,8 @@ int rte_vhost_driver_callback_register(const char *path,
  */
 uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
 
+struct rte_mbuf;
+struct rte_mempool;
 /**
  * This function adds buffers to the virtio devices RX virtqueue. Buffers can
  * be received from the physical port or from another virtual device. A packet
-- 
1.9.0

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

* [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (19 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-03-31  9:26       ` Maxime Coquelin
  2017-03-28 12:45     ` [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

It doesn't make any sense to invoke destroy_device() callback at
while handling SET_MEM_TABLE message.

>From the vhost-user spec, it's the GET_VRING_BASE message indicates
the end of a vhost device: the destroy_device() should be invoked
from there (luckily, we already did that).

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 lib/librte_vhost/vhost_user.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 40cc973..079c55e 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -496,12 +496,6 @@
 	uint32_t i;
 	int fd;
 
-	/* Remove from the data plane. */
-	if (dev->flags & VIRTIO_DEV_RUNNING) {
-		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		dev->notify_ops->destroy_device(dev->vid);
-	}
-
 	if (dev->mem) {
 		free_mem_region(dev);
 		rte_free(dev->mem);
-- 
1.9.0

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

* [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (20 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
@ 2017-03-28 12:45     ` Yuanhan Liu
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-28 12:45 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Now DPDK vhost lib has been generic enough, that it can be used to
implement any vhost-user drivers.

For example, this patch implements a very simple vhost-user net driver,
mainly for demonstrating how to use those generic vhost APIs.

And when the --builtin-net-driver option is used, the example virtio-net
driver code will be invoked, instead of the one provided from the vhost
library.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/vhost/Makefile     |   2 +-
 examples/vhost/main.c       |  37 +++-
 examples/vhost/main.h       |  29 +++-
 examples/vhost/virtio_net.c | 405 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 466 insertions(+), 7 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c

diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile
index e95c68a..af7be99 100644
--- a/examples/vhost/Makefile
+++ b/examples/vhost/Makefile
@@ -48,7 +48,7 @@ else
 APP = vhost-switch
 
 # all source are stored in SRCS-y
-SRCS-y := main.c
+SRCS-y := main.c virtio_net.c
 
 CFLAGS += -O2 -D_FILE_OFFSET_BITS=64
 CFLAGS += $(WERROR_FLAGS)
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 08b82f6..022438e 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,6 @@
 #define MBUF_CACHE_SIZE	128
 #define MBUF_DATA_SIZE	RTE_MBUF_DEFAULT_BUF_SIZE
 
-#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
 #define BURST_TX_DRAIN_US 100	/* TX drain every ~100us */
 
 #define BURST_RX_WAIT_US 15	/* Defines how long we wait between retries on RX */
@@ -129,6 +128,8 @@
 static int client_mode;
 static int dequeue_zero_copy;
 
+static int builtin_net_driver;
+
 /* Specify timeout (in useconds) between retries on RX. */
 static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
 /* Specify the number of retries on RX. */
@@ -499,6 +500,7 @@ struct mbuf_table {
 		{"tso", required_argument, NULL, 0},
 		{"client", no_argument, &client_mode, 1},
 		{"dequeue-zero-copy", no_argument, &dequeue_zero_copy, 1},
+		{"builtin-net-driver", no_argument, &builtin_net_driver, 1},
 		{NULL, 0, 0, 0},
 	};
 
@@ -795,7 +797,12 @@ static inline void __attribute__((always_inline))
 {
 	uint16_t ret;
 
-	ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	if (builtin_net_driver) {
+		ret = vs_enqueue_pkts(dst_vdev, VIRTIO_RXQ, &m, 1);
+	} else {
+		ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	}
+
 	if (enable_stats) {
 		rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
 		rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
@@ -1066,8 +1073,13 @@ static inline void __attribute__((always_inline))
 		}
 	}
 
-	enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+	if (builtin_net_driver) {
+		enqueue_count = vs_enqueue_pkts(vdev, VIRTIO_RXQ,
 						pkts, rx_count);
+	} else {
+		enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+						pkts, rx_count);
+	}
 	if (enable_stats) {
 		rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
 		rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
@@ -1083,8 +1095,13 @@ static inline void __attribute__((always_inline))
 	uint16_t count;
 	uint16_t i;
 
-	count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
+	if (builtin_net_driver) {
+		count = vs_dequeue_pkts(vdev, VIRTIO_TXQ, mbuf_pool,
 					pkts, MAX_PKT_BURST);
+	} else {
+		count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ,
+					mbuf_pool, pkts, MAX_PKT_BURST);
+	}
 
 	/* setup VMDq for the first packet */
 	if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
@@ -1187,6 +1204,9 @@ static inline void __attribute__((always_inline))
 		rte_pause();
 	}
 
+	if (builtin_net_driver)
+		vs_vhost_net_remove(vdev);
+
 	TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
 		     lcore_vdev_entry);
 	TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
@@ -1235,6 +1255,9 @@ static inline void __attribute__((always_inline))
 	}
 	vdev->vid = vid;
 
+	if (builtin_net_driver)
+		vs_vhost_net_setup(vdev);
+
 	TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
 	vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
 
@@ -1513,6 +1536,10 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+
+		if (builtin_net_driver)
+			rte_vhost_driver_set_features(file, VIRTIO_NET_FEATURES);
+
 		if (mergeable == 0) {
 			rte_vhost_driver_disable_features(file,
 				1ULL << VIRTIO_NET_F_MRG_RXBUF);
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index ddcd858..5ba7d38 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -43,8 +43,11 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
+#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
@@ -52,6 +55,12 @@ struct device_statistics {
 	rte_atomic64_t	rx_total_atomic;
 };
 
+struct vhost_queue {
+	struct rte_vhost_vring	vr;
+	uint16_t		last_avail_idx;
+	uint16_t		last_used_idx;
+};
+
 struct vhost_dev {
 	/**< Number of memory regions for gpa to hpa translation. */
 	uint32_t nregions_hpa;
@@ -69,9 +78,16 @@ struct vhost_dev {
 	volatile uint8_t remove;
 
 	int vid;
+	uint64_t features;
+	size_t hdr_len;
+	uint16_t nr_vrings;
+	struct rte_vhost_memory *mem;
 	struct device_statistics stats;
 	TAILQ_ENTRY(vhost_dev) global_vdev_entry;
 	TAILQ_ENTRY(vhost_dev) lcore_vdev_entry;
+
+#define MAX_QUEUE_PAIRS	4
+	struct vhost_queue queues[MAX_QUEUE_PAIRS * 2];
 } __rte_cache_aligned;
 
 TAILQ_HEAD(vhost_dev_tailq_list, vhost_dev);
@@ -92,4 +108,15 @@ struct lcore_info {
 	struct vhost_dev_tailq_list vdev_list;
 };
 
+/* we implement non-extra virtio net features */
+#define VIRTIO_NET_FEATURES	0
+
+void vs_vhost_net_setup(struct vhost_dev *dev);
+void vs_vhost_net_remove(struct vhost_dev *dev);
+uint16_t vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mbuf **pkts, uint32_t count);
+
+uint16_t vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mempool *mbuf_pool,
+			 struct rte_mbuf **pkts, uint16_t count);
 #endif /* _MAIN_H_ */
diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c
new file mode 100644
index 0000000..1c53174
--- /dev/null
+++ b/examples/vhost/virtio_net.c
@@ -0,0 +1,405 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <linux/virtio_net.h>
+
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_vhost.h>
+
+#include "main.h"
+
+/*
+ * A very simple vhost-user net driver implementation, without
+ * any extra features being enabled, such as TSO and mrg-Rx.
+ */
+
+void
+vs_vhost_net_setup(struct vhost_dev *dev)
+{
+	uint16_t i;
+	int vid = dev->vid;
+	struct vhost_queue *queue;
+
+	RTE_LOG(INFO, VHOST_CONFIG,
+		"setting builtin vhost-user net driver\n");
+
+	dev->features = rte_vhost_get_negotiated_features(vid);
+	if (dev->features &
+		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
+		dev->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+	} else {
+		dev->hdr_len = sizeof(struct virtio_net_hdr);
+	}
+
+	rte_vhost_get_mem_table(vid, &dev->mem);
+
+	dev->nr_vrings = rte_vhost_get_vring_num(vid);
+	for (i = 0; i < dev->nr_vrings; i++) {
+		queue = &dev->queues[i];
+
+		queue->last_used_idx  = 0;
+		queue->last_avail_idx = 0;
+		rte_vhost_get_vhost_vring(vid, i, &queue->vr);
+	}
+}
+
+void
+vs_vhost_net_remove(struct vhost_dev *dev)
+{
+	free(dev->mem);
+}
+
+static inline int __attribute__((always_inline))
+enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx)
+{
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
+	/* A counter to avoid desc dead loop chain */
+	uint16_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	/*
+	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
+	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
+	 * otherwise stores offset on the stack instead of in a register.
+	 */
+	if (unlikely(desc->len < dev->hdr_len) || !desc_addr)
+		return -1;
+
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	/* write virtio-net header */
+	*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+
+	desc_offset = dev->hdr_len;
+	desc_avail  = desc->len - dev->hdr_len;
+
+	mbuf_avail  = rte_pktmbuf_data_len(m);
+	mbuf_offset = 0;
+	while (mbuf_avail != 0 || m->next != NULL) {
+		/* done with current mbuf, fetch next */
+		if (mbuf_avail == 0) {
+			m = m->next;
+
+			mbuf_offset = 0;
+			mbuf_avail  = rte_pktmbuf_data_len(m);
+		}
+
+		/* done with current desc buf, fetch next */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0) {
+				/* Room in vring buffer is not enough */
+				return -1;
+			}
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+
+			desc = &vr->desc[desc->next];
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
+			rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+	}
+
+	return 0;
+}
+
+uint16_t
+vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+		struct rte_mbuf **pkts, uint32_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint16_t avail_idx, free_entries, start_idx;
+	uint16_t desc_indexes[MAX_PKT_BURST];
+	uint16_t used_idx;
+	uint32_t i;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	avail_idx = *((volatile uint16_t *)&vr->avail->idx);
+	start_idx = queue->last_used_idx;
+	free_entries = avail_idx - start_idx;
+	count = RTE_MIN(count, free_entries);
+	count = RTE_MIN(count, (uint32_t)MAX_PKT_BURST);
+	if (count == 0)
+		return 0;
+
+	/* Retrieve all of the desc indexes first to avoid caching issues. */
+	rte_prefetch0(&vr->avail->ring[start_idx & (vr->size - 1)]);
+	for (i = 0; i < count; i++) {
+		used_idx = (start_idx + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[used_idx];
+		vr->used->ring[used_idx].id = desc_indexes[i];
+		vr->used->ring[used_idx].len = pkts[i]->pkt_len +
+					       dev->hdr_len;
+	}
+
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		uint16_t desc_idx = desc_indexes[i];
+		int err;
+
+		err = enqueue_pkt(dev, vr, pkts[i], desc_idx);
+		if (unlikely(err)) {
+			used_idx = (start_idx + i) & (vr->size - 1);
+			vr->used->ring[used_idx].len = dev->hdr_len;
+		}
+
+		if (i + 1 < count)
+			rte_prefetch0(&vr->desc[desc_indexes[i+1]]);
+	}
+
+	rte_smp_wmb();
+
+	*(volatile uint16_t *)&vr->used->idx += count;
+	queue->last_used_idx += count;
+
+	/* flush used->idx update before we read avail->flags. */
+	rte_mb();
+
+	/* Kick the guest if necessary. */
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+	return count;
+}
+
+static inline int __attribute__((always_inline))
+dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx,
+	    struct rte_mempool *mbuf_pool)
+{
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct rte_mbuf *cur = m, *prev = m;
+	/* A counter to avoid desc dead loop chain */
+	uint32_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	if (unlikely((desc->len < dev->hdr_len)) ||
+			(desc->flags & VRING_DESC_F_INDIRECT))
+		return -1;
+
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+
+	/*
+	 * We don't support ANY_LAYOUT, neither VERSION_1, meaning
+	 * a Tx packet from guest must have 2 desc buffers at least:
+	 * the first for storing the header and the others for
+	 * storing the data.
+	 *
+	 * And since we don't support TSO, we could simply skip the
+	 * header.
+	 */
+	desc = &vr->desc[desc->next];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	desc_offset = 0;
+	desc_avail  = desc->len;
+	nr_desc    += 1;
+
+	mbuf_offset = 0;
+	mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
+	while (1) {
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
+						   mbuf_offset),
+			(void *)((uintptr_t)(desc_addr + desc_offset)),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+
+		/* This desc reaches to its end, get the next one */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0)
+				break;
+
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+			desc = &vr->desc[desc->next];
+
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+			rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		/*
+		 * This mbuf reaches to its end, get a new one
+		 * to hold more data.
+		 */
+		if (mbuf_avail == 0) {
+			cur = rte_pktmbuf_alloc(mbuf_pool);
+			if (unlikely(cur == NULL)) {
+				RTE_LOG(ERR, VHOST_DATA, "Failed to "
+					"allocate memory for mbuf.\n");
+				return -1;
+			}
+
+			prev->next = cur;
+			prev->data_len = mbuf_offset;
+			m->nb_segs += 1;
+			m->pkt_len += mbuf_offset;
+			prev = cur;
+
+			mbuf_offset = 0;
+			mbuf_avail  = cur->buf_len - RTE_PKTMBUF_HEADROOM;
+		}
+	}
+
+	prev->data_len = mbuf_offset;
+	m->pkt_len    += mbuf_offset;
+
+	return 0;
+}
+
+uint16_t
+vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint32_t desc_indexes[MAX_PKT_BURST];
+	uint32_t used_idx;
+	uint32_t i = 0;
+	uint16_t free_entries;
+	uint16_t avail_idx;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	free_entries = *((volatile uint16_t *)&vr->avail->idx) -
+			queue->last_avail_idx;
+	if (free_entries == 0)
+		return 0;
+
+	/* Prefetch available and used ring */
+	avail_idx = queue->last_avail_idx & (vr->size - 1);
+	used_idx  = queue->last_used_idx  & (vr->size - 1);
+	rte_prefetch0(&vr->avail->ring[avail_idx]);
+	rte_prefetch0(&vr->used->ring[used_idx]);
+
+	count = RTE_MIN(count, MAX_PKT_BURST);
+	count = RTE_MIN(count, free_entries);
+
+	/*
+	 * Retrieve all of the head indexes first and pre-update used entries
+	 * to avoid caching issues.
+	 */
+	for (i = 0; i < count; i++) {
+		avail_idx = (queue->last_avail_idx + i) & (vr->size - 1);
+		used_idx  = (queue->last_used_idx  + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[avail_idx];
+
+		vr->used->ring[used_idx].id  = desc_indexes[i];
+		vr->used->ring[used_idx].len = 0;
+	}
+
+	/* Prefetch descriptor index. */
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		int err;
+
+		if (likely(i + 1 < count))
+			rte_prefetch0(&vr->desc[desc_indexes[i + 1]]);
+
+		pkts[i] = rte_pktmbuf_alloc(mbuf_pool);
+		if (unlikely(pkts[i] == NULL)) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed to allocate memory for mbuf.\n");
+			break;
+		}
+
+		err = dequeue_pkt(dev, vr, pkts[i], desc_indexes[i], mbuf_pool);
+		if (unlikely(err)) {
+			rte_pktmbuf_free(pkts[i]);
+			break;
+		}
+
+	}
+	if (!i)
+		return 0;
+
+	queue->last_avail_idx += i;
+	queue->last_used_idx += i;
+	rte_smp_wmb();
+	rte_smp_rmb();
+
+	vr->used->idx += i;
+
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+
+	return i;
+}
-- 
1.9.0

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

* Re: [PATCH v3 03/22] vhost: use new APIs to handle features
  2017-03-28 12:45     ` [PATCH v3 03/22] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-03-29 14:57       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-29 14:57 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>
> v3: fix comment typo
> ---
>  examples/tep_termination/main.c        |  4 +++-
>  examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
>  lib/librte_vhost/rte_vhost_version.map |  3 ---
>  lib/librte_vhost/rte_virtio_net.h      | 13 ----------
>  lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
>  lib/librte_vhost/vhost.c               | 42 ---------------------------------
>  lib/librte_vhost/vhost.h               | 21 +++++++++++++++++
>  lib/librte_vhost/vhost_user.c          |  8 +++----
>  8 files changed, 77 insertions(+), 80 deletions(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 04/22] vhost: make notify ops per vhost driver
  2017-03-28 12:45     ` [PATCH v3 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-03-29 15:03       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-29 15:03 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Assume there is an application both support vhost-user net and
> vhost-user scsi, the callback should be different. Making notify
> ops per vhost driver allow application define different set of
> callbacks for different driver.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>
> v2: - check the return value of callback_register and callback_get
>     - update release note
> ---
>  doc/guides/prog_guide/vhost_lib.rst    |  2 +-
>  doc/guides/rel_notes/release_17_05.rst |  3 +++
>  drivers/net/vhost/rte_eth_vhost.c      | 20 +++++++++++---------
>  examples/tep_termination/main.c        |  7 ++++++-
>  examples/vhost/main.c                  |  9 +++++++--
>  lib/librte_vhost/rte_virtio_net.h      |  3 ++-
>  lib/librte_vhost/socket.c              | 32 ++++++++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.c               | 16 +---------------
>  lib/librte_vhost/vhost.h               |  5 ++++-
>  lib/librte_vhost/vhost_user.c          | 22 ++++++++++++++++------
>  10 files changed, 83 insertions(+), 36 deletions(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 06/22] vhost: introduce API to fetch negotiated features
  2017-03-28 12:45     ` [PATCH v3 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-03-31  7:45       ` Maxime Coquelin
  2017-03-31  8:51         ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  7:45 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 10 ++++++++++
>  lib/librte_vhost/vhost.c               | 12 ++++++++++++
>  3 files changed, 23 insertions(+)
>
> diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
> index 664a5f3..cec1e9e 100644
> --- a/lib/librte_vhost/rte_vhost_version.map
> +++ b/lib/librte_vhost/rte_vhost_version.map
> @@ -37,5 +37,6 @@ DPDK_17.05 {
>  	rte_vhost_driver_set_features;
>  	rte_vhost_get_mem_table;
>  	rte_vhost_get_mtu;
> +	rte_vhost_get_negotiated_features;
>
>  } DPDK_16.07;
> diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
> index 5a91f97..57e57e3 100644
> --- a/lib/librte_vhost/rte_virtio_net.h
> +++ b/lib/librte_vhost/rte_virtio_net.h
> @@ -154,6 +154,16 @@ struct virtio_net_device_ops {
>   */
>  uint64_t rte_vhost_driver_get_features(const char *path);
>
> +/**
> + * Get the feature bits after negotiation
> + *
> + * @param vid
> + *  Vhost device ID
> + * @return
> + *  Negotiated feature bits on success, 0 on failure
> + */
> +uint64_t rte_vhost_get_negotiated_features(int vid);
> +
>  /* Register callbacks. */
>  int rte_vhost_driver_callback_register(const char *path,
>  	struct virtio_net_device_ops const * const ops);
> diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
> index 2b41652..08dccfb 100644
> --- a/lib/librte_vhost/vhost.c
> +++ b/lib/librte_vhost/vhost.c
> @@ -359,6 +359,18 @@ struct virtio_net *
>  	return 0;
>  }
>
> +uint64_t
> +rte_vhost_get_negotiated_features(int vid)
> +{
> +	struct virtio_net *dev;
> +
> +	dev = get_device(vid);
> +	if (!dev)
> +		return 0;
It's unlikely to happen with net devices, but as this series is about
generalizing the use of this lib, couldn't we have cases where the
negotiated features is 0?

If so, shouldn't be preferable the caller passes features pointer as
argument?

> +
> +	return dev->features;
> +}
> +
>  int
>  rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
>  {
>

Thanks,
Maxime

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

* Re: [PATCH v3 07/22] vhost: export vhost vring info
  2017-03-28 12:45     ` [PATCH v3 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-31  7:48       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  7:48 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>
> v2: - fix off-by-one check
>     - add API comments
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 26 ++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.h               |  2 ++
>  4 files changed, 59 insertions(+)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 16/22] vhost: add features changed callback
  2017-03-28 12:45     ` [PATCH v3 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-03-31  7:50       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  7:50 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Features could be changed after the feature negotiation. For example,
> VHOST_F_LOG_ALL will be set/cleared at the start/end of live migration,
> respecitively. Thus, we need a new callback to inform the application
> on such change.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  doc/guides/prog_guide/vhost_lib.rst |  6 ++++++
>  lib/librte_vhost/rte_virtio_net.h   | 10 +++++++++-
>  lib/librte_vhost/vhost_user.c       |  5 +++++
>  3 files changed, 20 insertions(+), 1 deletion(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 17/22] vhost: export APIs for live migration support
  2017-03-28 12:45     ` [PATCH v3 17/22] vhost: export APIs for live migration support Yuanhan Liu
@ 2017-03-31  8:05       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  8:05 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> Export few APIs for the vhost-user driver to log the guest memory writes,
> which is a must for live migration support.
>
> This patch basically moves vhost_log_write() and vhost_log_used_vring()
> into vhost.h and then add an wrapper (the public API) to them.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost_version.map |  2 ++
>  lib/librte_vhost/rte_virtio_net.h      | 43 ++++++++++++++++++++++++++++++++++
>  lib/librte_vhost/vhost.c               | 31 ++++++++++++++++++++++++
>  lib/librte_vhost/vhost.h               | 38 ++++++++++++++++++++++++++++++
>  lib/librte_vhost/virtio_net.c          | 36 ----------------------------
>  5 files changed, 114 insertions(+), 36 deletions(-)

Reviewed-by: Maxime Coquelin <maximle.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 06/22] vhost: introduce API to fetch negotiated features
  2017-03-31  7:45       ` Maxime Coquelin
@ 2017-03-31  8:51         ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-03-31  8:51 UTC (permalink / raw)
  To: Maxime Coquelin; +Cc: dev, Harris James R, Liu Changpeng

On Fri, Mar 31, 2017 at 09:45:11AM +0200, Maxime Coquelin wrote:
> >+uint64_t
> >+rte_vhost_get_negotiated_features(int vid)
> >+{
> >+	struct virtio_net *dev;
> >+
> >+	dev = get_device(vid);
> >+	if (!dev)
> >+		return 0;
> It's unlikely to happen with net devices, but as this series is about
> generalizing the use of this lib, couldn't we have cases where the
> negotiated features is 0?

Yes, I think so.

> If so, shouldn't be preferable the caller passes features pointer as
> argument?

I thought of that. The reason I did that is to keep the semantics with
rte_vhost_driver_get_feature(path). But you are right, we don't have
to follow that. More importantly, we may also need change the return
value of rte_vhost_driver_get_features(path): which could also fail
if 'path' is not found.

	--yliu

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

* Re: [PATCH v3 18/22] vhost: introduce API to start a specific driver
  2017-03-28 12:45     ` [PATCH v3 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
@ 2017-03-31  9:11       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  9:11 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> We used to use rte_vhost_driver_session_start() to trigger the vhost-user
> session. It takes no argument, thus it's a global trigger. And it could
> be problematic.
>
> The issue is, currently, rte_vhost_driver_register(path, flags) actually
> tries to put it into the session loop (by fdset_add). However, it needs
> a set of APIs to set a vhost-user driver properly:
>   * rte_vhost_driver_register(path, flags);
>   * rte_vhost_driver_set_features(path, features);
>   * rte_vhost_driver_callback_register(path, vhost_device_ops);
>
> If a new vhost-user driver is registered after the trigger (think OVS-DPDK
> that could add a port dynamically from cmdline), the current code will
> effectively starts the session for the new driver just after the first
> API rte_vhost_driver_register() is invoked, leaving later calls taking
> no effect at all.
>
> To handle the case properly, this patch introduce a new API,
> rte_vhost_driver_start(path), to trigger a specific vhost-user driver.
> To do that, the rte_vhost_driver_register(path, flags) is simplified
> to create the socket only and let rte_vhost_driver_start(path) to
> actually put it into the session loop.
>
> Meanwhile, the rte_vhost_driver_session_start is removed: we could hide
> the session thread internally (create the thread if it has not been
> created). This would also simplify the application.
>
> NOTE: the API order in prog guide is slightly adjusted for showing the
> correct invoke order.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>
> v3: - fix broken reconnect
> ---
>  doc/guides/prog_guide/vhost_lib.rst    | 24 +++++-----
>  doc/guides/rel_notes/release_17_05.rst |  8 ++++
>  drivers/net/vhost/rte_eth_vhost.c      | 50 ++------------------
>  examples/tep_termination/main.c        |  8 +++-
>  examples/vhost/main.c                  |  9 +++-
>  lib/librte_vhost/fd_man.c              |  9 ++--
>  lib/librte_vhost/fd_man.h              |  2 +-
>  lib/librte_vhost/rte_vhost_version.map |  2 +-
>  lib/librte_vhost/rte_virtio_net.h      | 15 +++++-
>  lib/librte_vhost/socket.c              | 84 ++++++++++++++++++++--------------
>  10 files changed, 108 insertions(+), 103 deletions(-)
>

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header
  2017-03-28 12:45     ` [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
@ 2017-03-31  9:13       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  9:13 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> rte_mbuf struct is something more likely will be used only in vhost-user
> net driver, while we have made vhost-user generic enough that it can
> be used for implementing other drivers (such as vhost-user SCSI), they
> have also include <rte_mbuf.h>. Otherwise, the build will be broken.
>
> We could workaround it by using forward declaration, so that other
> non-net drivers won't need include <rte_mbuf.h>.
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/rte_vhost.h | 2 ++
>  1 file changed, 2 insertions(+)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* Re: [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message
  2017-03-28 12:45     ` [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
@ 2017-03-31  9:26       ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-03-31  9:26 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 03/28/2017 02:45 PM, Yuanhan Liu wrote:
> It doesn't make any sense to invoke destroy_device() callback at
> while handling SET_MEM_TABLE message.
>
> From the vhost-user spec, it's the GET_VRING_BASE message indicates
> the end of a vhost device: the destroy_device() should be invoked
> from there (luckily, we already did that).
>
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>  lib/librte_vhost/vhost_user.c | 6 ------
>  1 file changed, 6 deletions(-)

Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks,
Maxime

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

* [PATCH v4 00/22] vhost: generic vhost API
  2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
                       ` (21 preceding siblings ...)
  2017-03-28 12:45     ` [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
@ 2017-04-01  7:22     ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
                         ` (22 more replies)
  22 siblings, 23 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

This patchset makes DPDK vhost library generic enough, so that we could
build other vhost-user drivers on top of it. For example, SPDK (Storage
Performance Development Kit) is trying to enable vhost-user SCSI.

The basic idea is, let DPDK vhost be a vhost-user agent. It stores all
the info about the virtio device (i.e. vring address, negotiated features,
etc) and let the specific vhost-user driver to fetch them (by the API
provided by DPDK vhost lib). With those info being provided, the vhost-user
driver then could get/put vring entries, thus, it could exchange data
between the guest and host.

The last patch demonstrates how to use these new APIs to implement a
very simple vhost-user net driver, without any fancy features enabled.


Change log
==========

v2: - rebase
    - updated release note
    - updated API comments
    - renamed rte_vhost_get_vhost_memory to rte_vhost_get_mem_table

    - added a new device callback: features_changed(), bascially for live
      migration support
    - introduced rte_vhost_driver_start() to start a specific driver
    - misc fixes

v3: - rebaseon top of vhost-user socket fix
    - fix reconnect
    - fix shared build
    - fix typos

v4: - rebase
    - let rte_vhost_get.*_features() to return features by parameter and
      return -1 on failure
    - Follow the style of ring rework to update the release note: use one
      entry for all vhost changes and add sub items for each change.


Major API/ABI Changes summary
=============================

- some renames
  * "struct virtio_net_device_ops" ==> "struct vhost_device_ops"
  * "rte_virtio_net.h"  ==> "rte_vhost.h"

- driver related APIs are bond with the socket file
  * rte_vhost_driver_set_features(socket_file, features);
  * rte_vhost_driver_get_features(socket_file, features);
  * rte_vhost_driver_enable_features(socket_file, features)
  * rte_vhost_driver_disable_features(socket_file, features)
  * rte_vhost_driver_callback_register(socket_file, notify_ops);
  * rte_vhost_driver_start(socket_file);
    This function replaces rte_vhost_driver_session_start(). Check patch
    18 for more information.

- new APIs to fetch guest and vring info
  * rte_vhost_get_mem_table(vid, mem);
  * rte_vhost_get_negotiated_features(vid);
  * rte_vhost_get_vhost_vring(vid, vring_idx, vring);

- new exported structures 
  * struct rte_vhost_vring
  * struct rte_vhost_mem_region
  * struct rte_vhost_memory

- a new device ops callback: features_changed().


	--yliu

---
Yuanhan Liu (22):
  vhost: introduce driver features related APIs
  net/vhost: remove feature related APIs
  vhost: use new APIs to handle features
  vhost: make notify ops per vhost driver
  vhost: export guest memory regions
  vhost: introduce API to fetch negotiated features
  vhost: export vhost vring info
  vhost: export API to translate gpa to vva
  vhost: turn queue pair to vring
  vhost: export the number of vrings
  vhost: move the device ready check at proper place
  vhost: drop the Rx and Tx queue macro
  vhost: do not include net specific headers
  vhost: rename device ops struct
  vhost: rename virtio-net to vhost
  vhost: add features changed callback
  vhost: export APIs for live migration support
  vhost: introduce API to start a specific driver
  vhost: rename header file
  vhost: workaround the build dependency on mbuf header
  vhost: do not destroy device on repeat mem table message
  examples/vhost: demonstrate the new generic vhost APIs

 doc/guides/prog_guide/vhost_lib.rst         |  42 +--
 doc/guides/rel_notes/deprecation.rst        |   9 -
 doc/guides/rel_notes/release_17_05.rst      |  43 +++
 drivers/net/vhost/rte_eth_vhost.c           | 101 ++-----
 drivers/net/vhost/rte_eth_vhost.h           |  32 +--
 drivers/net/vhost/rte_pmd_vhost_version.map |   3 -
 examples/tep_termination/main.c             |  23 +-
 examples/tep_termination/main.h             |   2 +
 examples/tep_termination/vxlan_setup.c      |   2 +-
 examples/vhost/Makefile                     |   2 +-
 examples/vhost/main.c                       | 100 +++++--
 examples/vhost/main.h                       |  32 ++-
 examples/vhost/virtio_net.c                 | 405 ++++++++++++++++++++++++++
 lib/librte_vhost/Makefile                   |   4 +-
 lib/librte_vhost/fd_man.c                   |   9 +-
 lib/librte_vhost/fd_man.h                   |   2 +-
 lib/librte_vhost/rte_vhost.h                | 427 ++++++++++++++++++++++++++++
 lib/librte_vhost/rte_vhost_version.map      |  16 +-
 lib/librte_vhost/rte_virtio_net.h           | 208 --------------
 lib/librte_vhost/socket.c                   | 229 ++++++++++++---
 lib/librte_vhost/vhost.c                    | 230 ++++++++-------
 lib/librte_vhost/vhost.h                    | 113 +++++---
 lib/librte_vhost/vhost_user.c               | 121 ++++----
 lib/librte_vhost/vhost_user.h               |   2 +-
 lib/librte_vhost/virtio_net.c               |  71 ++---
 25 files changed, 1541 insertions(+), 687 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

-- 
1.9.0

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

* [PATCH v4 01/22] vhost: introduce driver features related APIs
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-05  0:01         ` Thomas Monjalon
  2017-04-01  7:22       ` [PATCH v4 02/22] net/vhost: remove feature " Yuanhan Liu
                         ` (21 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Introduce few APIs to set/get/enable/disable driver features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 10 +++-
 lib/librte_vhost/rte_vhost_version.map |  4 ++
 lib/librte_vhost/rte_virtio_net.h      | 53 ++++++++++++++++++++
 lib/librte_vhost/socket.c              | 92 ++++++++++++++++++++++++++++++++++
 4 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index f0862e6..6a4d206 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -53,7 +53,7 @@ vhost library should be able to:
 Vhost API Overview
 ------------------
 
-The following is an overview of the Vhost API functions:
+The following is an overview of some key Vhost API functions:
 
 * ``rte_vhost_driver_register(path, flags)``
 
@@ -110,6 +110,12 @@ The following is an overview of the Vhost API functions:
       of those segments, thus the fewer the segments, the quicker we will get
       the mapping. NOTE: we may speed it by using tree searching in future.
 
+* ``rte_vhost_driver_set_features(path, features)``
+
+  This function sets the feature bits the vhost-user driver supports. The
+  vhost-user driver could be vhost-user net, yet it could be something else,
+  say, vhost-user SCSI.
+
 * ``rte_vhost_driver_session_start()``
 
   This function starts the vhost session loop to handle vhost messages. It
@@ -145,7 +151,7 @@ The following is an overview of the Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_feature_disable/rte_vhost_feature_enable(feature_mask)``
+* ``rte_vhost_driver_disable/enable_features(path, features))``
 
   This function disables/enables some features. For example, it can be used to
   disable mergeable buffers and TSO features, which both are enabled by
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 30b4671..ca6259c 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -34,6 +34,10 @@ DPDK_16.07 {
 DPDK_17.05 {
 	global:
 
+	rte_vhost_driver_disable_features;
+	rte_vhost_driver_enable_features;
+	rte_vhost_driver_get_features;
+	rte_vhost_driver_set_features;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 56829aa..2c9ef8c 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -94,6 +94,59 @@ struct virtio_net_device_ops {
 /* Unregister vhost driver. This is only meaningful to vhost user. */
 int rte_vhost_driver_unregister(const char *path);
 
+/**
+ * Set the feature bits the vhost-user driver supports.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+
+/**
+ * Enable vhost-user driver features.
+ *
+ * Note that
+ * - the param @features should be a subset of the feature bits provided
+ *   by rte_vhost_driver_set_features().
+ * - it must be invoked before vhost-user negotiation starts.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to enable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+
+/**
+ * Disable vhost-user driver features.
+ *
+ * The two notes at rte_vhost_driver_enable_features() also apply here.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to disable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/**
+ * Get the feature bits before feature negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  A pointer to store the queried feature bits
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_get_features(const char *path, uint64_t *features);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
 /* Start vhost driver session blocking loop. */
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 2afde98..53663f4 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -67,6 +67,16 @@ struct vhost_user_socket {
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
+
+	/*
+	 * The "supported_features" indicates the feature bits the
+	 * vhost driver supports. The "features" indicates the feature
+	 * bits after the rte_vhost_driver_features_disable/enable().
+	 * It is also the final feature bits used for vhost-user
+	 * features negotiation.
+	 */
+	uint64_t supported_features;
+	uint64_t features;
 };
 
 struct vhost_user_connection {
@@ -490,6 +500,88 @@ struct vhost_user_reconnect_list {
 	return 0;
 }
 
+static struct vhost_user_socket *
+find_vhost_user_socket(const char *path)
+{
+	int i;
+
+	for (i = 0; i < vhost_user.vsocket_cnt; i++) {
+		struct vhost_user_socket *vsocket = vhost_user.vsockets[i];
+
+		if (!strcmp(vsocket->path, path))
+			return vsocket;
+	}
+
+	return NULL;
+}
+
+int
+rte_vhost_driver_disable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->features &= ~features;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_enable_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		if ((vsocket->supported_features & features) != features) {
+			/*
+			 * trying to enable features the driver doesn't
+			 * support.
+			 */
+			pthread_mutex_unlock(&vhost_user.mutex);
+			return -1;
+		}
+		vsocket->features |= features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_set_features(const char *path, uint64_t features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket) {
+		vsocket->supported_features = features;
+		vsocket->features = features;
+	}
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+int
+rte_vhost_driver_get_features(const char *path, uint64_t *features)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		*features = vsocket->features;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
 /*
  * Register a new vhost-user socket; here we could act as server
  * (the default case), or client (when RTE_VHOST_USER_CLIENT) flag
-- 
1.9.0

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

* [PATCH v4 02/22] net/vhost: remove feature related APIs
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 03/22] vhost: use new APIs to handle features Yuanhan Liu
                         ` (20 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The rte_eth_vhost_feature_disable/enable/get APIs are just a wrapper of
rte_vhost_feature_disable/enable/get. However, the later are going to
be refactored; it's going to take an extra parameter (socket_file path),
to let it be per-device.

Instead of changing those vhost-pmd APIs to adapt to the new vhost APIs,
we could simply remove them, and let vdev to serve this purpose. After
all, vdev options is better for disabling/enabling some features.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Acked-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - write more informative commit log on why they are removed.
    - update release note
---
 doc/guides/rel_notes/release_17_05.rst      | 13 +++++++++++++
 drivers/net/vhost/rte_eth_vhost.c           | 25 ------------------------
 drivers/net/vhost/rte_eth_vhost.h           | 30 -----------------------------
 drivers/net/vhost/rte_pmd_vhost_version.map |  3 ---
 4 files changed, 13 insertions(+), 58 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index d6c4616..e0432ea 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -192,6 +192,19 @@ API Changes
     flagged by the compiler. The return value usage should be checked
     while fixing the compiler error due to the extra parameter.
 
+* **Reworked rte_vhost library**
+
+  The rte_vhost library has been reworked to make it generic enough so that
+  user could build other vhost-user drivers on top of it. To achieve that,
+  following changes have been made:
+
+  * The following vhost-pmd APIs are removed:
+
+    * ``rte_eth_vhost_feature_disable``
+    * ``rte_eth_vhost_feature_enable``
+    * ``rte_eth_vhost_feature_get``
+
+
 ABI Changes
 -----------
 
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 3c6669f..762509b 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -975,31 +975,6 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-/**
- * Disable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_disable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_disable(feature_mask);
-}
-
-/**
- * Enable features in feature_mask. Returns 0 on success.
- */
-int
-rte_eth_vhost_feature_enable(uint64_t feature_mask)
-{
-	return rte_vhost_feature_enable(feature_mask);
-}
-
-/* Returns currently supported vhost features */
-uint64_t
-rte_eth_vhost_feature_get(void)
-{
-	return rte_vhost_feature_get();
-}
-
 static const struct eth_dev_ops ops = {
 	.dev_start = eth_dev_start,
 	.dev_stop = eth_dev_stop,
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index 7c98b1a..ea4bce4 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -43,36 +43,6 @@
 
 #include <rte_virtio_net.h>
 
-/**
- * Disable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- * Enable features in feature_mask.
- *
- * @param feature_mask
- *  Vhost features defined in "linux/virtio_net.h".
- * @return
- *  - On success, zero.
- *  - On failure, a negative value.
- */
-int rte_eth_vhost_feature_enable(uint64_t feature_mask);
-
-/**
- * Returns currently supported vhost features.
- *
- * @return
- *  Vhost features defined in "linux/virtio_net.h".
- */
-uint64_t rte_eth_vhost_feature_get(void);
-
 /*
  * Event description.
  */
diff --git a/drivers/net/vhost/rte_pmd_vhost_version.map b/drivers/net/vhost/rte_pmd_vhost_version.map
index 3d44083..695db85 100644
--- a/drivers/net/vhost/rte_pmd_vhost_version.map
+++ b/drivers/net/vhost/rte_pmd_vhost_version.map
@@ -1,9 +1,6 @@
 DPDK_16.04 {
 	global:
 
-	rte_eth_vhost_feature_disable;
-	rte_eth_vhost_feature_enable;
-	rte_eth_vhost_feature_get;
 	rte_eth_vhost_get_queue_event;
 
 	local: *;
-- 
1.9.0

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

* [PATCH v4 03/22] vhost: use new APIs to handle features
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 02/22] net/vhost: remove feature " Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
                         ` (19 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v3: fix comment typo
---
 examples/tep_termination/main.c        |  4 +++-
 examples/vhost/main.c                  | 43 +++++++++++++++++++++-------------
 lib/librte_vhost/rte_vhost_version.map |  3 ---
 lib/librte_vhost/rte_virtio_net.h      | 13 ----------
 lib/librte_vhost/socket.c              | 23 +++++++++++++++++-
 lib/librte_vhost/vhost.c               | 42 ---------------------------------
 lib/librte_vhost/vhost.h               | 21 +++++++++++++++++
 lib/librte_vhost/vhost_user.c          | 14 +++++++----
 8 files changed, 83 insertions(+), 80 deletions(-)

diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 20dafdb..8097dcd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1248,12 +1248,14 @@ static inline void __attribute__((always_inline))
 		rte_eal_remote_launch(switch_worker,
 			mbuf_pool, lcore_id);
 	}
-	rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
 	ret = rte_vhost_driver_register((char *)&dev_basename, 0);
 	if (ret != 0)
 		rte_exit(EXIT_FAILURE, "failed to register vhost driver.\n");
 
+	rte_vhost_driver_disable_features(dev_basename,
+		1ULL << VIRTIO_NET_F_MRG_RXBUF);
+
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
 
 	rte_vhost_driver_session_start();
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4789947..972a6a8 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -328,16 +328,6 @@ struct mbuf_table {
 
 	if (port >= rte_eth_dev_count()) return -1;
 
-	if (enable_tx_csum == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_CSUM);
-
-	if (enable_tso == 0) {
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_HOST_TSO6);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO4);
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_GUEST_TSO6);
-	}
-
 	rx_rings = (uint16_t)dev_info.max_rx_queues;
 	/* Configure ethernet device. */
 	retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf);
@@ -531,7 +521,6 @@ struct mbuf_table {
 			vmdq_conf_default.rx_adv_conf.vmdq_rx_conf.rx_mode =
 				ETH_VMDQ_ACCEPT_BROADCAST |
 				ETH_VMDQ_ACCEPT_MULTICAST;
-			rte_vhost_feature_enable(1ULL << VIRTIO_NET_F_CTRL_RX);
 
 			break;
 
@@ -1509,9 +1498,6 @@ static inline void __attribute__((always_inline))
 	RTE_LCORE_FOREACH_SLAVE(lcore_id)
 		rte_eal_remote_launch(switch_worker, NULL, lcore_id);
 
-	if (mergeable == 0)
-		rte_vhost_feature_disable(1ULL << VIRTIO_NET_F_MRG_RXBUF);
-
 	if (client_mode)
 		flags |= RTE_VHOST_USER_CLIENT;
 
@@ -1520,13 +1506,38 @@ static inline void __attribute__((always_inline))
 
 	/* Register vhost user driver to handle vhost messages. */
 	for (i = 0; i < nb_sockets; i++) {
-		ret = rte_vhost_driver_register
-				(socket_files + i * PATH_MAX, flags);
+		char *file = socket_files + i * PATH_MAX;
+		ret = rte_vhost_driver_register(file, flags);
 		if (ret != 0) {
 			unregister_drivers(i);
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+		if (mergeable == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_MRG_RXBUF);
+		}
+
+		if (enable_tx_csum == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_CSUM);
+		}
+
+		if (enable_tso == 0) {
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_HOST_TSO6);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO4);
+			rte_vhost_driver_disable_features(file,
+				1ULL << VIRTIO_NET_F_GUEST_TSO6);
+		}
+
+		if (promiscuous) {
+			rte_vhost_driver_enable_features(file,
+				1ULL << VIRTIO_NET_F_CTRL_RX);
+		}
 	}
 
 	rte_vhost_driver_callback_register(&virtio_net_device_ops);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index ca6259c..1150017 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -7,9 +7,6 @@ DPDK_2.0 {
 	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
-	rte_vhost_feature_disable;
-	rte_vhost_feature_enable;
-	rte_vhost_feature_get;
 
 	local: *;
 };
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 2c9ef8c..90db986 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -70,19 +70,6 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
-/**
- *  Disable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_disable(uint64_t feature_mask);
-
-/**
- *  Enable features in feature_mask. Returns 0 on success.
- */
-int rte_vhost_feature_enable(uint64_t feature_mask);
-
-/* Returns currently supported vhost features */
-uint64_t rte_vhost_feature_get(void);
-
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 53663f4..416b1fd 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -579,7 +579,13 @@ struct vhost_user_reconnect_list {
 		*features = vsocket->features;
 	pthread_mutex_unlock(&vhost_user.mutex);
 
-	return vsocket ? 0 : -1;
+	if (!vsocket) {
+		RTE_LOG(ERR, VHOST_CONFIG,
+			"socket file %s is not registered yet.\n", path);
+		return -1;
+	} else {
+		return 0;
+	}
 }
 
 /*
@@ -613,6 +619,21 @@ struct vhost_user_reconnect_list {
 	pthread_mutex_init(&vsocket->conn_mutex, NULL);
 	vsocket->dequeue_zero_copy = flags & RTE_VHOST_USER_DEQUEUE_ZERO_COPY;
 
+	/*
+	 * Set the supported features correctly for the builtin vhost-user
+	 * net driver.
+	 *
+	 * Applications know nothing about features the builtin virtio net
+	 * driver (virtio_net.c) supports, thus it's not possible for them
+	 * to invoke rte_vhost_driver_set_features(). To workaround it, here
+	 * we set it unconditionally. If the application want to implement
+	 * another vhost-user driver (say SCSI), it should call the
+	 * rte_vhost_driver_set_features(), which will overwrite following
+	 * two values.
+	 */
+	vsocket->supported_features = VIRTIO_NET_SUPPORTED_FEATURES;
+	vsocket->features           = VIRTIO_NET_SUPPORTED_FEATURES;
+
 	if ((flags & RTE_VHOST_USER_CLIENT) != 0) {
 		vsocket->reconnect = !(flags & RTE_VHOST_USER_NO_RECONNECT);
 		if (vsocket->reconnect && reconn_tid == 0) {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index dfb08db..7b40a92 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -49,28 +49,6 @@
 
 #include "vhost.h"
 
-#define VHOST_USER_F_PROTOCOL_FEATURES	30
-
-/* Features supported by this lib. */
-#define VHOST_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
-				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
-				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
-				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
-				(1ULL << VIRTIO_NET_F_MQ)      | \
-				(1ULL << VIRTIO_F_VERSION_1)   | \
-				(1ULL << VHOST_F_LOG_ALL)      | \
-				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
-				(1ULL << VIRTIO_NET_F_CSUM)    | \
-				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
-				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
-				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
-				(1ULL << VIRTIO_NET_F_MTU))
-
-uint64_t VHOST_FEATURES = VHOST_SUPPORTED_FEATURES;
-
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
 /* device ops to add/remove device to/from data core. */
@@ -419,26 +397,6 @@ struct virtio_net *
 	return 0;
 }
 
-uint64_t rte_vhost_feature_get(void)
-{
-	return VHOST_FEATURES;
-}
-
-int rte_vhost_feature_disable(uint64_t feature_mask)
-{
-	VHOST_FEATURES = VHOST_FEATURES & ~feature_mask;
-	return 0;
-}
-
-int rte_vhost_feature_enable(uint64_t feature_mask)
-{
-	if ((feature_mask & VHOST_SUPPORTED_FEATURES) == feature_mask) {
-		VHOST_FEATURES = VHOST_FEATURES | feature_mask;
-		return 0;
-	}
-	return -1;
-}
-
 /*
  * Register ops so that we can add/remove device to data core.
  */
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index daa9328..692691b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -133,6 +133,27 @@ struct vhost_virtqueue {
  #define VIRTIO_F_VERSION_1 32
 #endif
 
+#define VHOST_USER_F_PROTOCOL_FEATURES	30
+
+/* Features supported by this builtin vhost-user net driver. */
+#define VIRTIO_NET_SUPPORTED_FEATURES ((1ULL << VIRTIO_NET_F_MRG_RXBUF) | \
+				(1ULL << VIRTIO_NET_F_CTRL_VQ) | \
+				(1ULL << VIRTIO_NET_F_CTRL_RX) | \
+				(1ULL << VIRTIO_NET_F_GUEST_ANNOUNCE) | \
+				(1ULL << VIRTIO_NET_F_MQ)      | \
+				(1ULL << VIRTIO_F_VERSION_1)   | \
+				(1ULL << VHOST_F_LOG_ALL)      | \
+				(1ULL << VHOST_USER_F_PROTOCOL_FEATURES) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_HOST_TSO6) | \
+				(1ULL << VIRTIO_NET_F_CSUM)    | \
+				(1ULL << VIRTIO_NET_F_GUEST_CSUM) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+				(1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
+				(1ULL << VIRTIO_RING_F_INDIRECT_DESC) | \
+				(1ULL << VIRTIO_NET_F_MTU))
+
+
 struct guest_page {
 	uint64_t guest_phys_addr;
 	uint64_t host_phys_addr;
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7c6a5f7..72eb368 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -147,9 +147,12 @@
  * The features that we support are requested.
  */
 static uint64_t
-vhost_user_get_features(void)
+vhost_user_get_features(struct virtio_net *dev)
 {
-	return VHOST_FEATURES;
+	uint64_t features = 0;
+
+	rte_vhost_driver_get_features(dev->ifname, &features);
+	return features;
 }
 
 /*
@@ -158,7 +161,10 @@
 static int
 vhost_user_set_features(struct virtio_net *dev, uint64_t features)
 {
-	if (features & ~VHOST_FEATURES)
+	uint64_t vhost_features = 0;
+
+	rte_vhost_driver_get_features(dev->ifname, &vhost_features);
+	if (features & ~vhost_features)
 		return -1;
 
 	dev->features = features;
@@ -1006,7 +1012,7 @@
 
 	switch (msg.request) {
 	case VHOST_USER_GET_FEATURES:
-		msg.payload.u64 = vhost_user_get_features();
+		msg.payload.u64 = vhost_user_get_features(dev);
 		msg.size = sizeof(msg.payload.u64);
 		send_vhost_message(fd, &msg);
 		break;
-- 
1.9.0

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

* [PATCH v4 04/22] vhost: make notify ops per vhost driver
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (2 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 03/22] vhost: use new APIs to handle features Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 05/22] vhost: export guest memory regions Yuanhan Liu
                         ` (18 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Assume there is an application both support vhost-user net and
vhost-user scsi, the callback should be different. Making notify
ops per vhost driver allow application define different set of
callbacks for different driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - check the return value of callback_register and callback_get
    - update release note
---
 doc/guides/prog_guide/vhost_lib.rst    |  2 +-
 doc/guides/rel_notes/release_17_05.rst |  4 ++++
 drivers/net/vhost/rte_eth_vhost.c      | 20 +++++++++++---------
 examples/tep_termination/main.c        |  7 ++++++-
 examples/vhost/main.c                  |  9 +++++++--
 lib/librte_vhost/rte_virtio_net.h      |  3 ++-
 lib/librte_vhost/socket.c              | 32 ++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 16 +---------------
 lib/librte_vhost/vhost.h               |  5 ++++-
 lib/librte_vhost/vhost_user.c          | 22 ++++++++++++++++------
 10 files changed, 84 insertions(+), 36 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 6a4d206..40f3b3b 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index e0432ea..2a4a480 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -204,6 +204,10 @@ API Changes
     * ``rte_eth_vhost_feature_enable``
     * ``rte_eth_vhost_feature_get``
 
+  * The vhost API ``rte_vhost_driver_callback_register(ops)`` is reworked to
+    be per vhost-user socket file. Thus, it takes one more argument:
+    ``rte_vhost_driver_callback_register(path, ops)``.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 762509b..7504f89 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -669,6 +669,12 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
+static struct virtio_net_device_ops vhost_ops = {
+	.new_device          = new_device,
+	.destroy_device      = destroy_device,
+	.vring_state_changed = vring_state_changed,
+};
+
 int
 rte_eth_vhost_get_queue_event(uint8_t port_id,
 		struct rte_eth_vhost_queue_event *event)
@@ -738,15 +744,6 @@ struct vhost_xstats_name_off {
 static void *
 vhost_driver_session(void *param __rte_unused)
 {
-	static struct virtio_net_device_ops vhost_ops;
-
-	/* set vhost arguments */
-	vhost_ops.new_device = new_device;
-	vhost_ops.destroy_device = destroy_device;
-	vhost_ops.vring_state_changed = vring_state_changed;
-	if (rte_vhost_driver_callback_register(&vhost_ops) < 0)
-		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
-
 	/* start event handling */
 	rte_vhost_driver_session_start();
 
@@ -1090,6 +1087,11 @@ struct vhost_xstats_name_off {
 	if (rte_vhost_driver_register(iface_name, flags))
 		goto error;
 
+	if (rte_vhost_driver_callback_register(iface_name, &vhost_ops) < 0) {
+		RTE_LOG(ERR, PMD, "Can't register callbacks\n");
+		goto error;
+	}
+
 	/* We need only one message handling thread */
 	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
 		if (vhost_driver_session_start())
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 8097dcd..18b977e 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1256,7 +1256,12 @@ static inline void __attribute__((always_inline))
 	rte_vhost_driver_disable_features(dev_basename,
 		1ULL << VIRTIO_NET_F_MRG_RXBUF);
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+	ret = rte_vhost_driver_callback_register(dev_basename,
+		&virtio_net_device_ops);
+	if (ret != 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to register vhost driver callbacks.\n");
+	}
 
 	rte_vhost_driver_session_start();
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 972a6a8..72a9d69 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1538,9 +1538,14 @@ static inline void __attribute__((always_inline))
 			rte_vhost_driver_enable_features(file,
 				1ULL << VIRTIO_NET_F_CTRL_RX);
 		}
-	}
 
-	rte_vhost_driver_callback_register(&virtio_net_device_ops);
+		ret = rte_vhost_driver_callback_register(file,
+			&virtio_net_device_ops);
+		if (ret != 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to register vhost driver callbacks.\n");
+		}
+	}
 
 	rte_vhost_driver_session_start();
 	return 0;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 90db986..8c8e67e 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -135,7 +135,8 @@ struct virtio_net_device_ops {
 int rte_vhost_driver_get_features(const char *path, uint64_t *features);
 
 /* Register callbacks. */
-int rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const);
+int rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 416b1fd..aa948b9 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -77,6 +77,8 @@ struct vhost_user_socket {
 	 */
 	uint64_t supported_features;
 	uint64_t features;
+
+	struct virtio_net_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -743,6 +745,36 @@ struct vhost_user_reconnect_list {
 	return -1;
 }
 
+/*
+ * Register ops so that we can add/remove device to data core.
+ */
+int
+rte_vhost_driver_callback_register(const char *path,
+	struct virtio_net_device_ops const * const ops)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	if (vsocket)
+		vsocket->notify_ops = ops;
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? 0 : -1;
+}
+
+struct virtio_net_device_ops const *
+vhost_driver_callback_get(const char *path)
+{
+	struct vhost_user_socket *vsocket;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	return vsocket ? vsocket->notify_ops : NULL;
+}
+
 int
 rte_vhost_driver_session_start(void)
 {
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7b40a92..7d7bb3c 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -51,9 +51,6 @@
 
 struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* device ops to add/remove device to/from data core. */
-struct virtio_net_device_ops const *notify_ops;
-
 struct virtio_net *
 get_device(int vid)
 {
@@ -253,7 +250,7 @@ struct virtio_net *
 
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(vid);
+		dev->notify_ops->destroy_device(vid);
 	}
 
 	cleanup_device(dev, 1);
@@ -396,14 +393,3 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
-
-/*
- * Register ops so that we can add/remove device to data core.
- */
-int
-rte_vhost_driver_callback_register(struct virtio_net_device_ops const * const ops)
-{
-	notify_ops = ops;
-
-	return 0;
-}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 692691b..6186216 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -185,6 +185,8 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
+	struct virtio_net_device_ops const *notify_ops;
+
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
 	struct guest_page       *guest_pages;
@@ -288,7 +290,6 @@ static inline phys_addr_t __attribute__((always_inline))
 	return 0;
 }
 
-struct virtio_net_device_ops const *notify_ops;
 struct virtio_net *get_device(int vid);
 
 int vhost_new_device(void);
@@ -301,6 +302,8 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
+struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+
 /*
  * Backend-specific cleanup.
  *
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 72eb368..7fe07bc 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -135,7 +135,7 @@
 {
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	cleanup_device(dev, 0);
@@ -509,7 +509,7 @@
 	/* Remove from the data plane. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	if (dev->mem) {
@@ -693,7 +693,7 @@
 						"dequeue zero copy is enabled\n");
 			}
 
-			if (notify_ops->new_device(dev->vid) == 0)
+			if (dev->notify_ops->new_device(dev->vid) == 0)
 				dev->flags |= VIRTIO_DEV_RUNNING;
 		}
 	}
@@ -727,7 +727,7 @@
 	/* We have to stop the queue (virtio) if it is running. */
 	if (dev->flags & VIRTIO_DEV_RUNNING) {
 		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		notify_ops->destroy_device(dev->vid);
+		dev->notify_ops->destroy_device(dev->vid);
 	}
 
 	dev->flags &= ~VIRTIO_DEV_READY;
@@ -769,8 +769,8 @@
 		"set queue enable: %d to qp idx: %d\n",
 		enable, state->index);
 
-	if (notify_ops->vring_state_changed)
-		notify_ops->vring_state_changed(dev->vid, state->index, enable);
+	if (dev->notify_ops->vring_state_changed)
+		dev->notify_ops->vring_state_changed(dev->vid, state->index, enable);
 
 	dev->virtqueue[state->index]->enabled = enable;
 
@@ -984,6 +984,16 @@
 	if (dev == NULL)
 		return -1;
 
+	if (!dev->notify_ops) {
+		dev->notify_ops = vhost_driver_callback_get(dev->ifname);
+		if (!dev->notify_ops) {
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to get callback ops for driver %s\n",
+				dev->ifname);
+			return -1;
+		}
+	}
+
 	ret = read_vhost_message(fd, &msg);
 	if (ret <= 0 || msg.request >= VHOST_USER_MAX) {
 		if (ret < 0)
-- 
1.9.0

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

* [PATCH v4 05/22] vhost: export guest memory regions
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (3 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
                         ` (17 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Some vhost-user driver may need this info to setup its own page tables
for GPA (guest physical addr) to HPA (host physical addr) translation.
SPDK (Storage Performance Development Kit) is one example.

Besides, by exporting this memory info, we could also export the
gpa_to_vva() as an inline function, which helps for performance.
Otherwise, it has to be referenced indirectly by a "vid".

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 38 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 23 ++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 28 ++-----------------------
 lib/librte_vhost/vhost_user.c          | 12 +++++------
 5 files changed, 70 insertions(+), 32 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 1150017..664a5f3 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -35,6 +35,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 8c8e67e..8c1c172 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -59,6 +59,28 @@
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
 /**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+/**
  * Device and vring operations.
  */
 struct virtio_net_device_ops {
@@ -246,4 +268,20 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
 uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
 	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
 
+/**
+ * Get guest mem table: a list of memory regions.
+ *
+ * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
+ * guest memory regions. Application should free it at destroy_device()
+ * callback.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param mem
+ *  To store the returned mem regions
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 7d7bb3c..2b41652 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -359,6 +359,29 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
+{
+	struct virtio_net *dev;
+	struct rte_vhost_memory *m;
+	size_t size;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	size = dev->mem->nregions * sizeof(struct rte_vhost_mem_region);
+	m = malloc(size);
+	if (!m)
+		return -1;
+
+	m->nregions = dev->mem->nregions;
+	memcpy(m->regions, dev->mem->regions, size);
+	*mem = m;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6186216..6d1986a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -166,7 +166,7 @@ struct guest_page {
  */
 struct virtio_net {
 	/* Frontend (QEMU) memory and memory region information */
-	struct virtio_memory	*mem;
+	struct rte_vhost_memory	*mem;
 	uint64_t		features;
 	uint64_t		protocol_features;
 	int			vid;
@@ -192,30 +192,6 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct virtio_memory_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct virtio_memory {
-	uint32_t nregions;
-	struct virtio_memory_region regions[0];
-};
-
-
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
@@ -255,7 +231,7 @@ struct virtio_memory {
 static inline uint64_t __attribute__((always_inline))
 gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	for (i = 0; i < dev->mem->nregions; i++) {
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 7fe07bc..30cf8f8 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -92,7 +92,7 @@
 free_mem_region(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 
 	if (!dev || !dev->mem)
 		return;
@@ -310,7 +310,7 @@
 static uint64_t
 qva_to_vva(struct virtio_net *dev, uint64_t qva)
 {
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	uint32_t i;
 
 	/* Find the region where the address lives. */
@@ -438,7 +438,7 @@
 }
 
 static void
-add_guest_pages(struct virtio_net *dev, struct virtio_memory_region *reg,
+add_guest_pages(struct virtio_net *dev, struct rte_vhost_mem_region *reg,
 		uint64_t page_size)
 {
 	uint64_t reg_size = reg->size;
@@ -498,7 +498,7 @@
 vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
 	struct VhostUserMemory memory = pmsg->payload.memory;
-	struct virtio_memory_region *reg;
+	struct rte_vhost_mem_region *reg;
 	void *mmap_addr;
 	uint64_t mmap_size;
 	uint64_t mmap_offset;
@@ -525,8 +525,8 @@
 						sizeof(struct guest_page));
 	}
 
-	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct virtio_memory) +
-		sizeof(struct virtio_memory_region) * memory.nregions, 0);
+	dev->mem = rte_zmalloc("vhost-mem-table", sizeof(struct rte_vhost_memory) +
+		sizeof(struct rte_vhost_mem_region) * memory.nregions, 0);
 	if (dev->mem == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"(%d) failed to allocate memory for dev->mem\n",
-- 
1.9.0

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

* [PATCH v4 06/22] vhost: introduce API to fetch negotiated features
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (4 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 05/22] vhost: export guest memory regions Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  8:28         ` Maxime Coquelin
  2017-04-01  7:22       ` [PATCH v4 07/22] vhost: export vhost vring info Yuanhan Liu
                         ` (16 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---

v4: use parameter to store the returned features and return -1 on error
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 12 ++++++++++++
 lib/librte_vhost/vhost.c               | 13 +++++++++++++
 3 files changed, 26 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 664a5f3..cec1e9e 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -37,5 +37,6 @@ DPDK_17.05 {
 	rte_vhost_driver_set_features;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
+	rte_vhost_get_negotiated_features;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 8c1c172..c6fba0b 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -156,6 +156,18 @@ struct virtio_net_device_ops {
  */
 int rte_vhost_driver_get_features(const char *path, uint64_t *features);
 
+/**
+ * Get the feature bits after negotiation
+ *
+ * @param vid
+ *  Vhost device ID
+ * @param features
+ *  A pointer to store the queried feature bits
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_negotiated_features(int vid, uint64_t *features);
+
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct virtio_net_device_ops const * const ops);
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 2b41652..90b0f67 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -360,6 +360,19 @@ struct virtio_net *
 }
 
 int
+rte_vhost_get_negotiated_features(int vid, uint64_t *features)
+{
+	struct virtio_net *dev;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	*features = dev->features;
+	return 0;
+}
+
+int
 rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem)
 {
 	struct virtio_net *dev;
-- 
1.9.0

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

* [PATCH v4 07/22] vhost: export vhost vring info
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (5 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
                         ` (15 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - fix off-by-one check
    - add API comments
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 26 ++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 30 ++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               |  2 ++
 4 files changed, 59 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index cec1e9e..93b6733 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -38,5 +38,6 @@ DPDK_17.05 {
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
+	rte_vhost_get_vhost_vring;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index c6fba0b..39fec72 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -80,6 +80,17 @@ struct rte_vhost_memory {
 	struct rte_vhost_mem_region regions[0];
 };
 
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
 /**
  * Device and vring operations.
  */
@@ -296,4 +307,19 @@ uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
  */
 int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
 
+/**
+ * Get guest vring info, including the vring address, vring size, etc.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
 #endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 90b0f67..4b9d781 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -395,6 +395,36 @@ struct virtio_net *
 	return 0;
 }
 
+int
+rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			  struct rte_vhost_vring *vring)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (!dev)
+		return -1;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return -1;
+
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return -1;
+
+	vring->desc  = vq->desc;
+	vring->avail = vq->avail;
+	vring->used  = vq->used;
+	vring->log_guest_addr  = vq->log_guest_addr;
+
+	vring->callfd  = vq->callfd;
+	vring->kickfd  = vq->kickfd;
+	vring->size    = vq->size;
+
+	return 0;
+}
+
 uint16_t
 rte_vhost_avail_entries(int vid, uint16_t queue_id)
 {
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 6d1986a..68ca197 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -120,6 +120,8 @@ struct vhost_virtqueue {
 #ifndef VIRTIO_NET_F_MQ
  #define VIRTIO_NET_F_MQ		22
 #endif
+
+#define VHOST_MAX_VRING			0x100
 #define VHOST_MAX_QUEUE_PAIRS		0x80
 
 #ifndef VIRTIO_NET_F_MTU
-- 
1.9.0

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

* [PATCH v4 08/22] vhost: export API to translate gpa to vva
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (6 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 09/22] vhost: turn queue pair to vring Yuanhan Liu
                         ` (14 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 28 ++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 19 -------------------
 lib/librte_vhost/virtio_net.c          | 23 +++++++++++++----------
 4 files changed, 42 insertions(+), 29 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 93b6733..2b309b2 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -39,5 +39,6 @@ DPDK_17.05 {
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 39fec72..e019f98 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -103,6 +103,34 @@ struct virtio_net_device_ops {
 	void *reserved[5]; /**< Reserved for future extension */
 };
 
+/**
+ * Convert guest physical address to host virtual address
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 68ca197..b5c5046 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -229,25 +229,6 @@ struct virtio_net {
 #define MAX_VHOST_DEVICE	1024
 extern struct virtio_net *vhost_devices[MAX_VHOST_DEVICE];
 
-/* Convert guest physical Address to host virtual address */
-static inline uint64_t __attribute__((always_inline))
-gpa_to_vva(struct virtio_net *dev, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < dev->mem->nregions; i++) {
-		reg = &dev->mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
 /* Convert guest physical address to host physical address */
 static inline phys_addr_t __attribute__((always_inline))
 gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index d0a3b11..c1187d4 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -199,7 +199,7 @@ static inline int __attribute__((always_inline))
 	uint16_t nr_desc = 1;
 
 	desc = &descs[desc_idx];
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	/*
 	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
 	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
@@ -239,7 +239,7 @@ static inline int __attribute__((always_inline))
 				return -1;
 
 			desc = &descs[desc->next];
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -323,7 +323,8 @@ static inline uint32_t __attribute__((always_inline))
 		int err;
 
 		if (vq->desc[desc_idx].flags & VRING_DESC_F_INDIRECT) {
-			descs = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			descs = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_idx].addr);
 			if (unlikely(!descs)) {
 				count = i;
@@ -383,7 +384,7 @@ static inline int __attribute__((always_inline))
 
 	if (vq->desc[idx].flags & VRING_DESC_F_INDIRECT) {
 		descs = (struct vring_desc *)(uintptr_t)
-					gpa_to_vva(dev, vq->desc[idx].addr);
+			rte_vhost_gpa_to_vva(dev->mem, vq->desc[idx].addr);
 		if (unlikely(!descs))
 			return -1;
 
@@ -473,7 +474,7 @@ static inline int __attribute__((always_inline))
 	if (unlikely(m == NULL))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, buf_vec[vec_idx].buf_addr);
 	if (buf_vec[vec_idx].buf_len < dev->vhost_hlen || !desc_addr)
 		return -1;
 
@@ -495,7 +496,8 @@ static inline int __attribute__((always_inline))
 		/* done with current desc buf, get the next one */
 		if (desc_avail == 0) {
 			vec_idx++;
-			desc_addr = gpa_to_vva(dev, buf_vec[vec_idx].buf_addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem,
+					buf_vec[vec_idx].buf_addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -798,7 +800,7 @@ static inline int __attribute__((always_inline))
 			(desc->flags & VRING_DESC_F_INDIRECT))
 		return -1;
 
-	desc_addr = gpa_to_vva(dev, desc->addr);
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 	if (unlikely(!desc_addr))
 		return -1;
 
@@ -818,7 +820,7 @@ static inline int __attribute__((always_inline))
 		if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 			return -1;
 
-		desc_addr = gpa_to_vva(dev, desc->addr);
+		desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 		if (unlikely(!desc_addr))
 			return -1;
 
@@ -882,7 +884,7 @@ static inline int __attribute__((always_inline))
 			if (unlikely(desc->flags & VRING_DESC_F_INDIRECT))
 				return -1;
 
-			desc_addr = gpa_to_vva(dev, desc->addr);
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
 			if (unlikely(!desc_addr))
 				return -1;
 
@@ -1125,7 +1127,8 @@ static inline bool __attribute__((always_inline))
 			rte_prefetch0(&vq->desc[desc_indexes[i + 1]]);
 
 		if (vq->desc[desc_indexes[i]].flags & VRING_DESC_F_INDIRECT) {
-			desc = (struct vring_desc *)(uintptr_t)gpa_to_vva(dev,
+			desc = (struct vring_desc *)(uintptr_t)
+				rte_vhost_gpa_to_vva(dev->mem,
 					vq->desc[desc_indexes[i]].addr);
 			if (unlikely(!desc))
 				break;
-- 
1.9.0

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

* [PATCH v4 09/22] vhost: turn queue pair to vring
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (7 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 10/22] vhost: export the number of vrings Yuanhan Liu
                         ` (13 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

The queue pair is very virtio-net specific, other devices don't have
such concept. To make it generic, we should log the number of vrings
instead of the number of queue pairs.

This patch just does a simple convert, a later patch would export the
number of vrings to applications.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: enable all vrings by unconditionally
---
 lib/librte_vhost/vhost.c      | 80 +++++++++++++++----------------------------
 lib/librte_vhost/vhost.h      |  4 +--
 lib/librte_vhost/vhost_user.c | 28 +++++----------
 lib/librte_vhost/virtio_net.c | 10 +++---
 4 files changed, 42 insertions(+), 80 deletions(-)

diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 4b9d781..f0ed729 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -84,10 +84,8 @@ struct virtio_net *
 
 	vhost_backend_cleanup(dev);
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ], destroy);
-		cleanup_vq(dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ], destroy);
-	}
+	for (i = 0; i < dev->nr_vring; i++)
+		cleanup_vq(dev->virtqueue[i], destroy);
 }
 
 /*
@@ -97,24 +95,21 @@ struct virtio_net *
 free_device(struct virtio_net *dev)
 {
 	uint32_t i;
-	struct vhost_virtqueue *rxq, *txq;
+	struct vhost_virtqueue *vq;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rxq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		txq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		rte_free(rxq->shadow_used_ring);
-		rte_free(txq->shadow_used_ring);
+		rte_free(vq->shadow_used_ring);
 
-		/* rxq and txq are allocated together as queue-pair */
-		rte_free(rxq);
+		rte_free(vq);
 	}
 
 	rte_free(dev);
 }
 
 static void
-init_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+init_vring_queue(struct vhost_virtqueue *vq)
 {
 	memset(vq, 0, sizeof(struct vhost_virtqueue));
 
@@ -124,69 +119,48 @@ struct virtio_net *
 	/* Backends are set to -1 indicating an inactive device. */
 	vq->backend = -1;
 
-	/* always set the default vq pair to enabled */
-	if (qp_idx == 0)
-		vq->enabled = 1;
+	/*
+	 * always set the vq to enabled; this is to keep compatibility
+	 * with the old QEMU, whereas there is no SET_VRING_ENABLE message.
+	 */
+	vq->enabled = 1;
 
 	TAILQ_INIT(&vq->zmbuf_list);
 }
 
 static void
-init_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	init_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
-static void
-reset_vring_queue(struct vhost_virtqueue *vq, int qp_idx)
+reset_vring_queue(struct vhost_virtqueue *vq)
 {
 	int callfd;
 
 	callfd = vq->callfd;
-	init_vring_queue(vq, qp_idx);
+	init_vring_queue(vq);
 	vq->callfd = callfd;
 }
 
-static void
-reset_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
-{
-	uint32_t base_idx = qp_idx * VIRTIO_QNUM;
-
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_RXQ], qp_idx);
-	reset_vring_queue(dev->virtqueue[base_idx + VIRTIO_TXQ], qp_idx);
-}
-
 int
-alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx)
+alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)
 {
-	struct vhost_virtqueue *virtqueue = NULL;
-	uint32_t virt_rx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_RXQ;
-	uint32_t virt_tx_q_idx = qp_idx * VIRTIO_QNUM + VIRTIO_TXQ;
+	struct vhost_virtqueue *vq;
 
-	virtqueue = rte_malloc(NULL,
-			       sizeof(struct vhost_virtqueue) * VIRTIO_QNUM, 0);
-	if (virtqueue == NULL) {
+	vq = rte_malloc(NULL, sizeof(struct vhost_virtqueue), 0);
+	if (vq == NULL) {
 		RTE_LOG(ERR, VHOST_CONFIG,
-			"Failed to allocate memory for virt qp:%d.\n", qp_idx);
+			"Failed to allocate memory for vring:%u.\n", vring_idx);
 		return -1;
 	}
 
-	dev->virtqueue[virt_rx_q_idx] = virtqueue;
-	dev->virtqueue[virt_tx_q_idx] = virtqueue + VIRTIO_TXQ;
-
-	init_vring_queue_pair(dev, qp_idx);
+	dev->virtqueue[vring_idx] = vq;
+	init_vring_queue(vq);
 
-	dev->virt_qp_nb += 1;
+	dev->nr_vring += 1;
 
 	return 0;
 }
 
 /*
  * Reset some variables in device structure, while keeping few
- * others untouched, such as vid, ifname, virt_qp_nb: they
+ * others untouched, such as vid, ifname, nr_vring: they
  * should be same unless the device is removed.
  */
 void
@@ -198,8 +172,8 @@ struct virtio_net *
 	dev->protocol_features = 0;
 	dev->flags = 0;
 
-	for (i = 0; i < dev->virt_qp_nb; i++)
-		reset_vring_queue_pair(dev, i);
+	for (i = 0; i < dev->nr_vring; i++)
+		reset_vring_queue(dev->virtqueue[i]);
 }
 
 /*
@@ -340,7 +314,7 @@ struct virtio_net *
 	if (dev == NULL)
 		return 0;
 
-	return dev->virt_qp_nb;
+	return dev->nr_vring / 2;
 }
 
 int
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index b5c5046..84e379a 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -176,7 +176,7 @@ struct virtio_net {
 	uint16_t		vhost_hlen;
 	/* to tell if we need broadcast rarp packet */
 	rte_atomic16_t		broadcast_rarp;
-	uint32_t		virt_qp_nb;
+	uint32_t		nr_vring;
 	int			dequeue_zero_copy;
 	struct vhost_virtqueue	*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];
 #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
@@ -256,7 +256,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void reset_device(struct virtio_net *dev);
 void vhost_destroy_device(int);
 
-int alloc_vring_queue_pair(struct virtio_net *dev, uint32_t qp_idx);
+int alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx);
 
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 30cf8f8..4337ce7 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -233,13 +233,6 @@
 	struct vhost_virtqueue *old_vq, *vq;
 	int ret;
 
-	/*
-	 * vq is allocated on pairs, we should try to do realloc
-	 * on first queue of one queue pair only.
-	 */
-	if (index % VIRTIO_QNUM != 0)
-		return dev;
-
 	old_dev = dev;
 	vq = old_vq = dev->virtqueue[index];
 
@@ -257,8 +250,7 @@
 	if (oldnode != newnode) {
 		RTE_LOG(INFO, VHOST_CONFIG,
 			"reallocate vq from %d to %d node\n", oldnode, newnode);
-		vq = rte_malloc_socket(NULL, sizeof(*vq) * VIRTIO_QNUM, 0,
-				       newnode);
+		vq = rte_malloc_socket(NULL, sizeof(*vq), 0, newnode);
 		if (!vq)
 			return dev;
 
@@ -290,7 +282,6 @@
 
 out:
 	dev->virtqueue[index] = vq;
-	dev->virtqueue[index + 1] = vq + 1;
 	vhost_devices[dev->vid] = dev;
 
 	return dev;
@@ -621,14 +612,13 @@
 static int
 virtio_is_ready(struct virtio_net *dev)
 {
-	struct vhost_virtqueue *rvq, *tvq;
+	struct vhost_virtqueue *vq;
 	uint32_t i;
 
-	for (i = 0; i < dev->virt_qp_nb; i++) {
-		rvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_RXQ];
-		tvq = dev->virtqueue[i * VIRTIO_QNUM + VIRTIO_TXQ];
+	for (i = 0; i < dev->nr_vring; i++) {
+		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(rvq) || !vq_is_ready(tvq)) {
+		if (!vq_is_ready(vq)) {
 			RTE_LOG(INFO, VHOST_CONFIG,
 				"virtio is not ready for processing.\n");
 			return 0;
@@ -940,7 +930,6 @@
 vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev, VhostUserMsg *msg)
 {
 	uint16_t vring_idx;
-	uint16_t qp_idx;
 
 	switch (msg->request) {
 	case VHOST_USER_SET_VRING_KICK:
@@ -960,17 +949,16 @@
 		return 0;
 	}
 
-	qp_idx = vring_idx / VIRTIO_QNUM;
-	if (qp_idx >= VHOST_MAX_QUEUE_PAIRS) {
+	if (vring_idx >= VHOST_MAX_VRING) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"invalid vring index: %u\n", vring_idx);
 		return -1;
 	}
 
-	if (dev->virtqueue[qp_idx])
+	if (dev->virtqueue[vring_idx])
 		return 0;
 
-	return alloc_vring_queue_pair(dev, qp_idx);
+	return alloc_vring_queue(dev, vring_idx);
 }
 
 int
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index c1187d4..28542cf 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -86,9 +86,9 @@ static inline void __attribute__((always_inline))
 }
 
 static bool
-is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t qp_nb)
+is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
 {
-	return (is_tx ^ (idx & 1)) == 0 && idx < qp_nb * VIRTIO_QNUM;
+	return (is_tx ^ (idx & 1)) == 0 && idx < nr_vring;
 }
 
 static inline void __attribute__((always_inline))
@@ -283,7 +283,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint32_t i, sz;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -554,7 +554,7 @@ static inline uint32_t __attribute__((always_inline))
 	uint16_t avail_head;
 
 	LOG_DEBUG(VHOST_DATA, "(%d) %s\n", dev->vid, __func__);
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 0, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
@@ -1019,7 +1019,7 @@ static inline bool __attribute__((always_inline))
 	if (!dev)
 		return 0;
 
-	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->virt_qp_nb))) {
+	if (unlikely(!is_valid_virt_queue_idx(queue_id, 1, dev->nr_vring))) {
 		RTE_LOG(ERR, VHOST_DATA, "(%d) %s: invalid virtqueue idx %d.\n",
 			dev->vid, __func__, queue_id);
 		return 0;
-- 
1.9.0

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

* [PATCH v4 10/22] vhost: export the number of vrings
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (8 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 11/22] vhost: move the device ready check at proper place Yuanhan Liu
                         ` (12 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_get_queue_num() for telling how many vrings.
However, the return value is the number of "queue pairs", which is
very virtio-net specific. To make it generic, we should return the
number of vrings instead, and let the driver do the proper translation.
Say, virtio-net driver could turn it to the number of queue pairs by
dividing 2.

Meanwhile, mark rte_vhost_get_queue_num as deprecated.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst |  3 +++
 drivers/net/vhost/rte_eth_vhost.c      |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  1 +
 lib/librte_vhost/rte_virtio_net.h      | 17 +++++++++++++++++
 lib/librte_vhost/vhost.c               | 11 +++++++++++
 5 files changed, 33 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 2a4a480..5dc5b87 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -208,6 +208,9 @@ API Changes
     be per vhost-user socket file. Thus, it takes one more argument:
     ``rte_vhost_driver_callback_register(path, ops)``.
 
+  * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
+    ``rte_vhost_get_vring_num`` should be used.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 7504f89..5435bd6 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -569,7 +569,7 @@ struct vhost_xstats_name_off {
 		vq->port = eth_dev->data->port_id;
 	}
 
-	for (i = 0; i < rte_vhost_get_queue_num(vid) * VIRTIO_QNUM; i++)
+	for (i = 0; i < rte_vhost_get_vring_num(vid); i++)
 		rte_vhost_enable_guest_notification(vid, i, 0);
 
 	rte_vhost_get_mtu(vid, &eth_dev->data->mtu);
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 2b309b2..8df14dc 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -39,6 +39,7 @@ DPDK_17.05 {
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
 	rte_vhost_get_vhost_vring;
+	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index e019f98..9c1809e 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -241,17 +241,34 @@ int rte_vhost_driver_callback_register(const char *path,
 int rte_vhost_get_numa_node(int vid);
 
 /**
+ * @deprecated
  * Get the number of queues the device supports.
  *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
  * @param vid
  *  virtio-net device ID
  *
  * @return
  *  The number of queues, 0 on failure
  */
+__rte_deprecated
 uint32_t rte_vhost_get_queue_num(int vid);
 
 /**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
  * Get the virtio net device's ifname, which is the vhost-user socket
  * file path.
  *
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index f0ed729..d57d4b2 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -317,6 +317,17 @@ struct virtio_net *
 	return dev->nr_vring / 2;
 }
 
+uint16_t
+rte_vhost_get_vring_num(int vid)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return 0;
+
+	return dev->nr_vring;
+}
+
 int
 rte_vhost_get_ifname(int vid, char *buf, size_t len)
 {
-- 
1.9.0

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

* [PATCH v4 11/22] vhost: move the device ready check at proper place
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (9 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
                         ` (11 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Currently, we check vq->desc, vq->kickfd and vq->callfd to know whether
a virtio device is ready or not. However, we only do it when handling
SET_VRING_KICK message, which could be wrong if a vhost-user frontend
send SET_VRING_KICK first and SET_VRING_CALL later.

To work for all possible vhost-user frontend implementations, we could
move the ready check at the end of vhost-user message handler.

Meanwhile, since we do the check more often than before, the "virtio
not ready" message is dropped, to not flood the screen.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/vhost_user.c | 40 ++++++++++++++++++----------------------
 1 file changed, 18 insertions(+), 22 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 4337ce7..9140f60 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -615,14 +615,14 @@
 	struct vhost_virtqueue *vq;
 	uint32_t i;
 
+	if (dev->nr_vring == 0)
+		return 0;
+
 	for (i = 0; i < dev->nr_vring; i++) {
 		vq = dev->virtqueue[i];
 
-		if (!vq_is_ready(vq)) {
-			RTE_LOG(INFO, VHOST_CONFIG,
-				"virtio is not ready for processing.\n");
+		if (!vq_is_ready(vq))
 			return 0;
-		}
 	}
 
 	RTE_LOG(INFO, VHOST_CONFIG,
@@ -651,10 +651,6 @@
 	vq->callfd = file.fd;
 }
 
-/*
- *  In vhost-user, when we receive kick message, will test whether virtio
- *  device is ready for packet processing.
- */
 static void
 vhost_user_set_vring_kick(struct virtio_net *dev, struct VhostUserMsg *pmsg)
 {
@@ -673,20 +669,6 @@
 	if (vq->kickfd >= 0)
 		close(vq->kickfd);
 	vq->kickfd = file.fd;
-
-	if (virtio_is_ready(dev)) {
-		dev->flags |= VIRTIO_DEV_READY;
-
-		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
-			if (dev->dequeue_zero_copy) {
-				RTE_LOG(INFO, VHOST_CONFIG,
-						"dequeue zero copy is enabled\n");
-			}
-
-			if (dev->notify_ops->new_device(dev->vid) == 0)
-				dev->flags |= VIRTIO_DEV_RUNNING;
-		}
-	}
 }
 
 static void
@@ -1108,5 +1090,19 @@
 		send_vhost_message(fd, &msg);
 	}
 
+	if (!(dev->flags & VIRTIO_DEV_RUNNING) && virtio_is_ready(dev)) {
+		dev->flags |= VIRTIO_DEV_READY;
+
+		if (!(dev->flags & VIRTIO_DEV_RUNNING)) {
+			if (dev->dequeue_zero_copy) {
+				RTE_LOG(INFO, VHOST_CONFIG,
+						"dequeue zero copy is enabled\n");
+			}
+
+			if (dev->notify_ops->new_device(dev->vid) == 0)
+				dev->flags |= VIRTIO_DEV_RUNNING;
+		}
+	}
+
 	return 0;
 }
-- 
1.9.0

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

* [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (10 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 11/22] vhost: move the device ready check at proper place Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-05  0:17         ` Thomas Monjalon
  2017-04-01  7:22       ` [PATCH v4 13/22] vhost: do not include net specific headers Yuanhan Liu
                         ` (10 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

They are virtio-net specific and should be defined inside the virtio-net
driver.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 6 ++++++
 drivers/net/vhost/rte_eth_vhost.c      | 2 ++
 examples/tep_termination/main.h        | 2 ++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 3 ---
 5 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 5dc5b87..471a509 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -211,6 +211,12 @@ API Changes
   * The vhost API ``rte_vhost_get_queue_num`` is deprecated, instead,
     ``rte_vhost_get_vring_num`` should be used.
 
+  * Following macros are removed in ``rte_virtio_net.h``
+
+    * ``VIRTIO_RXQ``
+    * ``VIRTIO_TXQ``
+    * ``VIRTIO_QNUM``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 5435bd6..f6e49da 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -45,6 +45,8 @@
 
 #include "rte_eth_vhost.h"
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 #define ETH_VHOST_IFACE_ARG		"iface"
 #define ETH_VHOST_QUEUES_ARG		"queues"
 #define ETH_VHOST_CLIENT_ARG		"client"
diff --git a/examples/tep_termination/main.h b/examples/tep_termination/main.h
index c0ea766..8ed817d 100644
--- a/examples/tep_termination/main.h
+++ b/examples/tep_termination/main.h
@@ -54,6 +54,8 @@
 /* Max number of devices. Limited by the application. */
 #define MAX_DEVICES 64
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 /* Per-device statistics struct */
 struct device_statistics {
 	uint64_t tx_total;
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 6bb42e8..7a3d251 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -41,6 +41,8 @@
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
 #define RTE_LOGTYPE_VHOST_PORT   RTE_LOGTYPE_USER3
 
+enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 9c1809e..c6e11e9 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -55,9 +55,6 @@
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
 #define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
 
-/* Enum for virtqueue management. */
-enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
-
 /**
  * Information relating to memory regions including offsets to
  * addresses in QEMUs memory file.
-- 
1.9.0

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

* [PATCH v4 13/22] vhost: do not include net specific headers
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (11 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 14/22] vhost: rename device ops struct Yuanhan Liu
                         ` (9 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Include it internally, at vhost.h.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v2: - update release note
---
 doc/guides/rel_notes/release_17_05.rst | 7 +++++++
 examples/vhost/main.h                  | 2 ++
 lib/librte_vhost/rte_virtio_net.h      | 4 ----
 lib/librte_vhost/vhost.h               | 4 ++++
 4 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index 471a509..ebc28f5 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -217,6 +217,13 @@ API Changes
     * ``VIRTIO_TXQ``
     * ``VIRTIO_QNUM``
 
+  * Following net specific header files are removed in ``rte_virtio_net.h``
+
+    * ``linux/virtio_net.h``
+    * ``sys/socket.h``
+    * ``linux/if.h``
+    * ``rte_ether.h``
+
 
 ABI Changes
 -----------
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index 7a3d251..ddcd858 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -36,6 +36,8 @@
 
 #include <sys/queue.h>
 
+#include <rte_ether.h>
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER2
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index c6e11e9..9915751 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -42,14 +42,10 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 #include <linux/virtio_ring.h>
-#include <linux/virtio_net.h>
 #include <sys/eventfd.h>
-#include <sys/socket.h>
-#include <linux/if.h>
 
 #include <rte_memory.h>
 #include <rte_mempool.h>
-#include <rte_ether.h>
 
 #define RTE_VHOST_USER_CLIENT		(1ULL << 0)
 #define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 84e379a..672098b 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -39,8 +39,12 @@
 #include <sys/queue.h>
 #include <unistd.h>
 #include <linux/vhost.h>
+#include <linux/virtio_net.h>
+#include <sys/socket.h>
+#include <linux/if.h>
 
 #include <rte_log.h>
+#include <rte_ether.h>
 
 #include "rte_virtio_net.h"
 
-- 
1.9.0

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

* [PATCH v4 14/22] vhost: rename device ops struct
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (12 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 13/22] vhost: do not include net specific headers Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
                         ` (8 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rename "virtio_net_device_ops" to "vhost_device_ops", to not let it
be virtio-net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst    | 2 +-
 doc/guides/rel_notes/release_17_05.rst | 3 +++
 drivers/net/vhost/rte_eth_vhost.c      | 2 +-
 examples/tep_termination/main.c        | 2 +-
 examples/vhost/main.c                  | 2 +-
 lib/librte_vhost/Makefile              | 2 +-
 lib/librte_vhost/rte_virtio_net.h      | 4 ++--
 lib/librte_vhost/socket.c              | 6 +++---
 lib/librte_vhost/vhost.h               | 4 ++--
 9 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 40f3b3b..e6e34f3 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -122,7 +122,7 @@ The following is an overview of some key Vhost API functions:
   starts an infinite loop, therefore it should be called in a dedicated
   thread.
 
-* ``rte_vhost_driver_callback_register(path, virtio_net_device_ops)``
+* ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
   the appropriate action when some events happen. The following events are
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index ebc28f5..a400bd0 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -224,6 +224,9 @@ API Changes
     * ``linux/if.h``
     * ``rte_ether.h``
 
+  * The vhost struct ``virtio_net_device_ops`` is renamed to
+    ``vhost_device_ops``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index f6e49da..0b514cc 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -671,7 +671,7 @@ struct vhost_xstats_name_off {
 	return 0;
 }
 
-static struct virtio_net_device_ops vhost_ops = {
+static struct vhost_device_ops vhost_ops = {
 	.new_device          = new_device,
 	.destroy_device      = destroy_device,
 	.vring_state_changed = vring_state_changed,
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 18b977e..738f2d2 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1081,7 +1081,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops = {
+static const struct vhost_device_ops virtio_net_device_ops = {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
 };
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 72a9d69..4395306 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1270,7 +1270,7 @@ static inline void __attribute__((always_inline))
  * These callback allow devices to be added to the data core when configuration
  * has been fully complete.
  */
-static const struct virtio_net_device_ops virtio_net_device_ops =
+static const struct vhost_device_ops virtio_net_device_ops =
 {
 	.new_device =  new_device,
 	.destroy_device = destroy_device,
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 1b224b3..1262dcc 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -36,7 +36,7 @@ LIB = librte_vhost.a
 
 EXPORT_MAP := rte_vhost_version.map
 
-LIBABIVER := 3
+LIBABIVER := 4
 
 CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 -D_FILE_OFFSET_BITS=64
 CFLAGS += -I vhost_user
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 9915751..4287c68 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -87,7 +87,7 @@ struct rte_vhost_vring {
 /**
  * Device and vring operations.
  */
-struct virtio_net_device_ops {
+struct vhost_device_ops {
 	int (*new_device)(int vid);		/**< Add device. */
 	void (*destroy_device)(int vid);	/**< Remove device. */
 
@@ -202,7 +202,7 @@ static inline uint64_t __attribute__((always_inline))
 
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops);
+	struct vhost_device_ops const * const ops);
 /* Start vhost driver session blocking loop. */
 int rte_vhost_driver_session_start(void);
 
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index aa948b9..3b68fc9 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -78,7 +78,7 @@ struct vhost_user_socket {
 	uint64_t supported_features;
 	uint64_t features;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 };
 
 struct vhost_user_connection {
@@ -750,7 +750,7 @@ struct vhost_user_reconnect_list {
  */
 int
 rte_vhost_driver_callback_register(const char *path,
-	struct virtio_net_device_ops const * const ops)
+	struct vhost_device_ops const * const ops)
 {
 	struct vhost_user_socket *vsocket;
 
@@ -763,7 +763,7 @@ struct vhost_user_reconnect_list {
 	return vsocket ? 0 : -1;
 }
 
-struct virtio_net_device_ops const *
+struct vhost_device_ops const *
 vhost_driver_callback_get(const char *path)
 {
 	struct vhost_user_socket *vsocket;
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 672098b..225ff2e 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -191,7 +191,7 @@ struct virtio_net {
 	struct ether_addr	mac;
 	uint16_t		mtu;
 
-	struct virtio_net_device_ops const *notify_ops;
+	struct vhost_device_ops const *notify_ops;
 
 	uint32_t		nr_guest_pages;
 	uint32_t		max_guest_pages;
@@ -265,7 +265,7 @@ static inline phys_addr_t __attribute__((always_inline))
 void vhost_set_ifname(int, const char *if_name, unsigned int if_len);
 void vhost_enable_dequeue_zero_copy(int vid);
 
-struct virtio_net_device_ops const *vhost_driver_callback_get(const char *path);
+struct vhost_device_ops const *vhost_driver_callback_get(const char *path);
 
 /*
  * Backend-specific cleanup.
-- 
1.9.0

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

* [PATCH v4 15/22] vhost: rename virtio-net to vhost
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (13 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 16/22] vhost: add features changed callback Yuanhan Liu
                         ` (7 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "virtio-net" to "vhost" in the API comments and vhost prog guide.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 +++---
 lib/librte_vhost/rte_virtio_net.h   | 14 +++++++-------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index e6e34f3..88f0591 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -130,12 +130,12 @@ The following is an overview of some key Vhost API functions:
 
   * ``new_device(int vid)``
 
-    This callback is invoked when a virtio net device becomes ready. ``vid``
-    is the virtio net device ID.
+    This callback is invoked when a virtio device becomes ready. ``vid``
+    is the vhost device ID.
 
   * ``destroy_device(int vid)``
 
-    This callback is invoked when a virtio net device shuts down (or when the
+    This callback is invoked when a virtio device shuts down (or when the
     vhost connection is broken).
 
   * ``vring_state_changed(int vid, uint16_t queue_id, int enable)``
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 4287c68..442f851 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -226,7 +226,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * is allocated.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The numa node, -1 on failure
@@ -238,11 +238,11 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get the number of queues the device supports.
  *
  * Note this function is deprecated, as it returns a queue pair number,
- * which is virtio-net specific. Instead, rte_vhost_get_vring_num should
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
  * be used.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  *
  * @return
  *  The number of queues, 0 on failure
@@ -266,7 +266,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * file path.
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param buf
  *  The buffer to stored the queried ifname
  * @param len
@@ -281,7 +281,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * Get how many avail entries are left in the queue
  *
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index
  *
@@ -296,7 +296,7 @@ int rte_vhost_driver_callback_register(const char *path,
  * count is returned to indicate the number of packets that were succesfully
  * added to the RX queue.
  * @param vid
- *  virtio-net device ID
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param pkts
@@ -314,7 +314,7 @@ uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
  * construct host mbufs, copies guest buffer content to host mbufs and
  * store them in pkts to be processed.
  * @param vid
- *  virtio-net device
+ *  vhost device ID
  * @param queue_id
  *  virtio queue index in mq case
  * @param mbuf_pool
-- 
1.9.0

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

* [PATCH v4 16/22] vhost: add features changed callback
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (14 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 17/22] vhost: export APIs for live migration support Yuanhan Liu
                         ` (6 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Features could be changed after the feature negotiation. For example,
VHOST_F_LOG_ALL will be set/cleared at the start/end of live migration,
respecitively. Thus, we need a new callback to inform the application
on such change.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/prog_guide/vhost_lib.rst |  6 ++++++
 lib/librte_vhost/rte_virtio_net.h   | 10 +++++++++-
 lib/librte_vhost/vhost_user.c       |  5 +++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index 88f0591..a4fb1f1 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -143,6 +143,12 @@ The following is an overview of some key Vhost API functions:
     This callback is invoked when a specific queue's state is changed, for
     example to enabled or disabled.
 
+  * ``features_changed(int vid, uint64_t features)``
+
+    This callback is invoked when the features is changed. For example,
+    ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
+    migration, respectively.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 442f851..ec52a9b 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -93,7 +93,15 @@ struct vhost_device_ops {
 
 	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
 
-	void *reserved[5]; /**< Reserved for future extension */
+	/**
+	 * Features could be changed after the feature negotiation.
+	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
+	 * start/end of live migration, respectively. This callback
+	 * is used to inform the application on such change.
+	 */
+	int (*features_changed)(int vid, uint64_t features);
+
+	void *reserved[4]; /**< Reserved for future extension */
 };
 
 /**
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 9140f60..bade6ad 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -167,6 +167,11 @@
 	if (features & ~vhost_features)
 		return -1;
 
+	if ((dev->flags & VIRTIO_DEV_RUNNING) && dev->features != features) {
+		if (dev->notify_ops->features_changed)
+			dev->notify_ops->features_changed(dev->vid, features);
+	}
+
 	dev->features = features;
 	if (dev->features &
 		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
-- 
1.9.0

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

* [PATCH v4 17/22] vhost: export APIs for live migration support
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (15 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
                         ` (5 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Export few APIs for the vhost-user driver to log the guest memory writes,
which is a must for live migration support.

This patch basically moves vhost_log_write() and vhost_log_used_vring()
into vhost.h and then add an wrapper (the public API) to them.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/rte_vhost_version.map |  2 ++
 lib/librte_vhost/rte_virtio_net.h      | 43 ++++++++++++++++++++++++++++++++++
 lib/librte_vhost/vhost.c               | 31 ++++++++++++++++++++++++
 lib/librte_vhost/vhost.h               | 38 ++++++++++++++++++++++++++++++
 lib/librte_vhost/virtio_net.c          | 36 ----------------------------
 5 files changed, 114 insertions(+), 36 deletions(-)

diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index 8df14dc..f4b74da 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -41,5 +41,7 @@ DPDK_17.05 {
 	rte_vhost_get_vhost_vring;
 	rte_vhost_get_vring_num;
 	rte_vhost_gpa_to_vva;
+	rte_vhost_log_used_vring;
+	rte_vhost_log_write;
 
 } DPDK_16.07;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index ec52a9b..7a08bbf 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -132,6 +132,49 @@ static inline uint64_t __attribute__((always_inline))
 	return 0;
 }
 
+#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
+
+/**
+ * Log the memory write start with given address.
+ *
+ * This function only need be invoked when the live migration starts.
+ * Therefore, we won't need call it at all in the most of time. For
+ * making the performance impact be minimum, it's suggested to do a
+ * check before calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_write(vid, addr, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param addr
+ *  the starting address for write
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
+
+/**
+ * Log the used ring update start at given offset.
+ *
+ * Same as rte_vhost_log_write, it's suggested to do a check before
+ * calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  the vring index
+ * @param offset
+ *  the offset inside the used ring
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			      uint64_t offset, uint64_t len);
+
 int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
 
 /**
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index d57d4b2..59de2ea 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -444,3 +444,34 @@ struct virtio_net *
 	dev->virtqueue[queue_id]->used->flags = VRING_USED_F_NO_NOTIFY;
 	return 0;
 }
+
+void
+rte_vhost_log_write(int vid, uint64_t addr, uint64_t len)
+{
+	struct virtio_net *dev = get_device(vid);
+
+	if (dev == NULL)
+		return;
+
+	vhost_log_write(dev, addr, len);
+}
+
+void
+rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			 uint64_t offset, uint64_t len)
+{
+	struct virtio_net *dev;
+	struct vhost_virtqueue *vq;
+
+	dev = get_device(vid);
+	if (dev == NULL)
+		return;
+
+	if (vring_idx >= VHOST_MAX_VRING)
+		return;
+	vq = dev->virtqueue[vring_idx];
+	if (!vq)
+		return;
+
+	vhost_log_used_vring(dev, vq, offset, len);
+}
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index 225ff2e..a199ee6 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -198,6 +198,44 @@ struct virtio_net {
 	struct guest_page       *guest_pages;
 } __rte_cache_aligned;
 
+
+#define VHOST_LOG_PAGE	4096
+
+static inline void __attribute__((always_inline))
+vhost_log_page(uint8_t *log_base, uint64_t page)
+{
+	log_base[page / 8] |= 1 << (page % 8);
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
+{
+	uint64_t page;
+
+	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
+		   !dev->log_base || !len))
+		return;
+
+	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
+		return;
+
+	/* To make sure guest memory updates are committed before logging */
+	rte_smp_wmb();
+
+	page = addr / VHOST_LOG_PAGE;
+	while (page * VHOST_LOG_PAGE < addr + len) {
+		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
+		page += 1;
+	}
+}
+
+static inline void __attribute__((always_inline))
+vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
+		     uint64_t offset, uint64_t len)
+{
+	vhost_log_write(dev, vq->log_guest_addr + offset, len);
+}
+
 /* Macros for printing using RTE_LOG */
 #define RTE_LOGTYPE_VHOST_CONFIG RTE_LOGTYPE_USER1
 #define RTE_LOGTYPE_VHOST_DATA   RTE_LOGTYPE_USER1
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index 28542cf..fc336d9 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -48,42 +48,6 @@
 #include "vhost.h"
 
 #define MAX_PKT_BURST 32
-#define VHOST_LOG_PAGE	4096
-
-static inline void __attribute__((always_inline))
-vhost_log_page(uint8_t *log_base, uint64_t page)
-{
-	log_base[page / 8] |= 1 << (page % 8);
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_write(struct virtio_net *dev, uint64_t addr, uint64_t len)
-{
-	uint64_t page;
-
-	if (likely(((dev->features & (1ULL << VHOST_F_LOG_ALL)) == 0) ||
-		   !dev->log_base || !len))
-		return;
-
-	if (unlikely(dev->log_size <= ((addr + len - 1) / VHOST_LOG_PAGE / 8)))
-		return;
-
-	/* To make sure guest memory updates are committed before logging */
-	rte_smp_wmb();
-
-	page = addr / VHOST_LOG_PAGE;
-	while (page * VHOST_LOG_PAGE < addr + len) {
-		vhost_log_page((uint8_t *)(uintptr_t)dev->log_base, page);
-		page += 1;
-	}
-}
-
-static inline void __attribute__((always_inline))
-vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq,
-		     uint64_t offset, uint64_t len)
-{
-	vhost_log_write(dev, vq->log_guest_addr + offset, len);
-}
 
 static bool
 is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_t nr_vring)
-- 
1.9.0

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

* [PATCH v4 18/22] vhost: introduce API to start a specific driver
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (16 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 17/22] vhost: export APIs for live migration support Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 19/22] vhost: rename header file Yuanhan Liu
                         ` (4 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

We used to use rte_vhost_driver_session_start() to trigger the vhost-user
session. It takes no argument, thus it's a global trigger. And it could
be problematic.

The issue is, currently, rte_vhost_driver_register(path, flags) actually
tries to put it into the session loop (by fdset_add). However, it needs
a set of APIs to set a vhost-user driver properly:
  * rte_vhost_driver_register(path, flags);
  * rte_vhost_driver_set_features(path, features);
  * rte_vhost_driver_callback_register(path, vhost_device_ops);

If a new vhost-user driver is registered after the trigger (think OVS-DPDK
that could add a port dynamically from cmdline), the current code will
effectively starts the session for the new driver just after the first
API rte_vhost_driver_register() is invoked, leaving later calls taking
no effect at all.

To handle the case properly, this patch introduce a new API,
rte_vhost_driver_start(path), to trigger a specific vhost-user driver.
To do that, the rte_vhost_driver_register(path, flags) is simplified
to create the socket only and let rte_vhost_driver_start(path) to
actually put it into the session loop.

Meanwhile, the rte_vhost_driver_session_start is removed: we could hide
the session thread internally (create the thread if it has not been
created). This would also simplify the application.

NOTE: the API order in prog guide is slightly adjusted for showing the
correct invoke order.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---

v3: - fix broken reconnect
---
 doc/guides/prog_guide/vhost_lib.rst    | 24 +++++-----
 doc/guides/rel_notes/release_17_05.rst |  4 ++
 drivers/net/vhost/rte_eth_vhost.c      | 50 ++------------------
 examples/tep_termination/main.c        |  8 +++-
 examples/vhost/main.c                  |  9 +++-
 lib/librte_vhost/fd_man.c              |  9 ++--
 lib/librte_vhost/fd_man.h              |  2 +-
 lib/librte_vhost/rte_vhost_version.map |  2 +-
 lib/librte_vhost/rte_virtio_net.h      | 15 +++++-
 lib/librte_vhost/socket.c              | 84 ++++++++++++++++++++--------------
 10 files changed, 104 insertions(+), 103 deletions(-)

diff --git a/doc/guides/prog_guide/vhost_lib.rst b/doc/guides/prog_guide/vhost_lib.rst
index a4fb1f1..5979290 100644
--- a/doc/guides/prog_guide/vhost_lib.rst
+++ b/doc/guides/prog_guide/vhost_lib.rst
@@ -116,12 +116,6 @@ The following is an overview of some key Vhost API functions:
   vhost-user driver could be vhost-user net, yet it could be something else,
   say, vhost-user SCSI.
 
-* ``rte_vhost_driver_session_start()``
-
-  This function starts the vhost session loop to handle vhost messages. It
-  starts an infinite loop, therefore it should be called in a dedicated
-  thread.
-
 * ``rte_vhost_driver_callback_register(path, vhost_device_ops)``
 
   This function registers a set of callbacks, to let DPDK applications take
@@ -149,6 +143,17 @@ The following is an overview of some key Vhost API functions:
     ``VHOST_F_LOG_ALL`` will be set/cleared at the start/end of live
     migration, respectively.
 
+* ``rte_vhost_driver_disable/enable_features(path, features))``
+
+  This function disables/enables some features. For example, it can be used to
+  disable mergeable buffers and TSO features, which both are enabled by
+  default.
+
+* ``rte_vhost_driver_start(path)``
+
+  This function triggers the vhost-user negotiation. It should be invoked at
+  the end of initializing a vhost-user driver.
+
 * ``rte_vhost_enqueue_burst(vid, queue_id, pkts, count)``
 
   Transmits (enqueues) ``count`` packets from host to guest.
@@ -157,13 +162,6 @@ The following is an overview of some key Vhost API functions:
 
   Receives (dequeues) ``count`` packets from guest, and stored them at ``pkts``.
 
-* ``rte_vhost_driver_disable/enable_features(path, features))``
-
-  This function disables/enables some features. For example, it can be used to
-  disable mergeable buffers and TSO features, which both are enabled by
-  default.
-
-
 Vhost-user Implementations
 --------------------------
 
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index a400bd0..ed206d2 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -227,6 +227,10 @@ API Changes
   * The vhost struct ``virtio_net_device_ops`` is renamed to
     ``vhost_device_ops``
 
+  * The vhost API ``rte_vhost_driver_session_start`` is removed. Instead,
+    ``rte_vhost_driver_start`` should be used, and no need to create a
+    thread to call it.
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 0b514cc..0a4c476 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -127,9 +127,6 @@ struct internal_list {
 
 static pthread_mutex_t internal_list_lock = PTHREAD_MUTEX_INITIALIZER;
 
-static rte_atomic16_t nb_started_ports;
-static pthread_t session_th;
-
 static struct rte_eth_link pmd_link = {
 		.link_speed = 10000,
 		.link_duplex = ETH_LINK_FULL_DUPLEX,
@@ -743,42 +740,6 @@ struct vhost_xstats_name_off {
 	return vid;
 }
 
-static void *
-vhost_driver_session(void *param __rte_unused)
-{
-	/* start event handling */
-	rte_vhost_driver_session_start();
-
-	return NULL;
-}
-
-static int
-vhost_driver_session_start(void)
-{
-	int ret;
-
-	ret = pthread_create(&session_th,
-			NULL, vhost_driver_session, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't create a thread\n");
-
-	return ret;
-}
-
-static void
-vhost_driver_session_stop(void)
-{
-	int ret;
-
-	ret = pthread_cancel(session_th);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't cancel the thread\n");
-
-	ret = pthread_join(session_th, NULL);
-	if (ret)
-		RTE_LOG(ERR, PMD, "Can't join the thread\n");
-}
-
 static int
 eth_dev_start(struct rte_eth_dev *dev)
 {
@@ -1094,10 +1055,10 @@ struct vhost_xstats_name_off {
 		goto error;
 	}
 
-	/* We need only one message handling thread */
-	if (rte_atomic16_add_return(&nb_started_ports, 1) == 1) {
-		if (vhost_driver_session_start())
-			goto error;
+	if (rte_vhost_driver_start(iface_name) < 0) {
+		RTE_LOG(ERR, PMD, "Failed to start driver for %s\n",
+			iface_name);
+		goto error;
 	}
 
 	return data->port_id;
@@ -1224,9 +1185,6 @@ struct vhost_xstats_name_off {
 
 	eth_dev_close(eth_dev);
 
-	if (rte_atomic16_sub_return(&nb_started_ports, 1) == 0)
-		vhost_driver_session_stop();
-
 	rte_free(vring_states[eth_dev->data->port_id]);
 	vring_states[eth_dev->data->port_id] = NULL;
 
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 738f2d2..24c62cd 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -1263,7 +1263,13 @@ static inline void __attribute__((always_inline))
 			"failed to register vhost driver callbacks.\n");
 	}
 
-	rte_vhost_driver_session_start();
+	if (rte_vhost_driver_start(dev_basename) < 0) {
+		rte_exit(EXIT_FAILURE,
+			"failed to start vhost driver.\n");
+	}
+
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
 
 	return 0;
 }
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 4395306..64b3eea 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1545,9 +1545,16 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"failed to register vhost driver callbacks.\n");
 		}
+
+		if (rte_vhost_driver_start(file) < 0) {
+			rte_exit(EXIT_FAILURE,
+				"failed to start vhost driver.\n");
+		}
 	}
 
-	rte_vhost_driver_session_start();
+	RTE_LCORE_FOREACH_SLAVE(lcore_id)
+		rte_eal_wait_lcore(lcore_id);
+
 	return 0;
 
 }
diff --git a/lib/librte_vhost/fd_man.c b/lib/librte_vhost/fd_man.c
index c7a4490..2ceacc9 100644
--- a/lib/librte_vhost/fd_man.c
+++ b/lib/librte_vhost/fd_man.c
@@ -210,8 +210,8 @@
  * will wait until the flag is reset to zero(which indicates the callback is
  * finished), then it could free the context after fdset_del.
  */
-void
-fdset_event_dispatch(struct fdset *pfdset)
+void *
+fdset_event_dispatch(void *arg)
 {
 	int i;
 	struct pollfd *pfd;
@@ -221,9 +221,10 @@
 	int fd, numfds;
 	int remove1, remove2;
 	int need_shrink;
+	struct fdset *pfdset = arg;
 
 	if (pfdset == NULL)
-		return;
+		return NULL;
 
 	while (1) {
 
@@ -294,4 +295,6 @@
 		if (need_shrink)
 			fdset_shrink(pfdset);
 	}
+
+	return NULL;
 }
diff --git a/lib/librte_vhost/fd_man.h b/lib/librte_vhost/fd_man.h
index d319cac..90d34db 100644
--- a/lib/librte_vhost/fd_man.h
+++ b/lib/librte_vhost/fd_man.h
@@ -64,6 +64,6 @@ int fdset_add(struct fdset *pfdset, int fd,
 
 void *fdset_del(struct fdset *pfdset, int fd);
 
-void fdset_event_dispatch(struct fdset *pfdset);
+void *fdset_event_dispatch(void *arg);
 
 #endif
diff --git a/lib/librte_vhost/rte_vhost_version.map b/lib/librte_vhost/rte_vhost_version.map
index f4b74da..0785873 100644
--- a/lib/librte_vhost/rte_vhost_version.map
+++ b/lib/librte_vhost/rte_vhost_version.map
@@ -4,7 +4,6 @@ DPDK_2.0 {
 	rte_vhost_dequeue_burst;
 	rte_vhost_driver_callback_register;
 	rte_vhost_driver_register;
-	rte_vhost_driver_session_start;
 	rte_vhost_enable_guest_notification;
 	rte_vhost_enqueue_burst;
 
@@ -35,6 +34,7 @@ DPDK_17.05 {
 	rte_vhost_driver_enable_features;
 	rte_vhost_driver_get_features;
 	rte_vhost_driver_set_features;
+	rte_vhost_driver_start;
 	rte_vhost_get_mem_table;
 	rte_vhost_get_mtu;
 	rte_vhost_get_negotiated_features;
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
index 7a08bbf..890f4b2 100644
--- a/lib/librte_vhost/rte_virtio_net.h
+++ b/lib/librte_vhost/rte_virtio_net.h
@@ -254,8 +254,19 @@ void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
 /* Register callbacks. */
 int rte_vhost_driver_callback_register(const char *path,
 	struct vhost_device_ops const * const ops);
-/* Start vhost driver session blocking loop. */
-int rte_vhost_driver_session_start(void);
+
+/**
+ *
+ * Start the vhost-user driver.
+ *
+ * This function triggers the vhost-user negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_start(const char *path);
 
 /**
  * Get the MTU value of the device if set in QEMU.
diff --git a/lib/librte_vhost/socket.c b/lib/librte_vhost/socket.c
index 3b68fc9..66fd335 100644
--- a/lib/librte_vhost/socket.c
+++ b/lib/librte_vhost/socket.c
@@ -63,7 +63,8 @@ struct vhost_user_socket {
 	struct vhost_user_connection_list conn_list;
 	pthread_mutex_t conn_mutex;
 	char *path;
-	int listenfd;
+	int socket_fd;
+	struct sockaddr_un un;
 	bool is_server;
 	bool reconnect;
 	bool dequeue_zero_copy;
@@ -101,7 +102,8 @@ struct vhost_user {
 
 static void vhost_user_server_new_connection(int fd, void *data, int *remove);
 static void vhost_user_read_cb(int fd, void *dat, int *remove);
-static int vhost_user_create_client(struct vhost_user_socket *vsocket);
+static int create_unix_socket(struct vhost_user_socket *vsocket);
+static int vhost_user_start_client(struct vhost_user_socket *vsocket);
 
 static struct vhost_user vhost_user = {
 	.fdset = {
@@ -280,23 +282,26 @@ struct vhost_user {
 
 		free(conn);
 
-		if (vsocket->reconnect)
-			vhost_user_create_client(vsocket);
+		if (vsocket->reconnect) {
+			create_unix_socket(vsocket);
+			vhost_user_start_client(vsocket);
+		}
 	}
 }
 
 static int
-create_unix_socket(const char *path, struct sockaddr_un *un, bool is_server)
+create_unix_socket(struct vhost_user_socket *vsocket)
 {
 	int fd;
+	struct sockaddr_un *un = &vsocket->un;
 
 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	if (fd < 0)
 		return -1;
 	RTE_LOG(INFO, VHOST_CONFIG, "vhost-user %s: socket created, fd: %d\n",
-		is_server ? "server" : "client", fd);
+		vsocket->is_server ? "server" : "client", fd);
 
-	if (!is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
+	if (!vsocket->is_server && fcntl(fd, F_SETFL, O_NONBLOCK)) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"vhost-user: can't set nonblocking mode for socket, fd: "
 			"%d (%s)\n", fd, strerror(errno));
@@ -306,25 +311,21 @@ struct vhost_user {
 
 	memset(un, 0, sizeof(*un));
 	un->sun_family = AF_UNIX;
-	strncpy(un->sun_path, path, sizeof(un->sun_path));
+	strncpy(un->sun_path, vsocket->path, sizeof(un->sun_path));
 	un->sun_path[sizeof(un->sun_path) - 1] = '\0';
 
-	return fd;
+	vsocket->socket_fd = fd;
+	return 0;
 }
 
 static int
-vhost_user_create_server(struct vhost_user_socket *vsocket)
+vhost_user_start_server(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = bind(fd, (struct sockaddr *)&un, sizeof(un));
+	ret = bind(fd, (struct sockaddr *)&vsocket->un, sizeof(vsocket->un));
 	if (ret < 0) {
 		RTE_LOG(ERR, VHOST_CONFIG,
 			"failed to bind to %s: %s; remove it and try again\n",
@@ -337,7 +338,6 @@ struct vhost_user {
 	if (ret < 0)
 		goto err;
 
-	vsocket->listenfd = fd;
 	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
 		  NULL, vsocket);
 	if (ret < 0) {
@@ -456,20 +456,15 @@ struct vhost_user_reconnect_list {
 }
 
 static int
-vhost_user_create_client(struct vhost_user_socket *vsocket)
+vhost_user_start_client(struct vhost_user_socket *vsocket)
 {
-	int fd;
 	int ret;
-	struct sockaddr_un un;
+	int fd = vsocket->socket_fd;
 	const char *path = vsocket->path;
 	struct vhost_user_reconnect *reconn;
 
-	fd = create_unix_socket(path, &un, vsocket->is_server);
-	if (fd < 0)
-		return -1;
-
-	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&un,
-					  sizeof(un));
+	ret = vhost_user_connect_nonblock(fd, (struct sockaddr *)&vsocket->un,
+					  sizeof(vsocket->un));
 	if (ret == 0) {
 		vhost_user_add_connection(fd, vsocket);
 		return 0;
@@ -492,7 +487,7 @@ struct vhost_user_reconnect_list {
 		close(fd);
 		return -1;
 	}
-	reconn->un = un;
+	reconn->un = vsocket->un;
 	reconn->fd = fd;
 	reconn->vsocket = vsocket;
 	pthread_mutex_lock(&reconn_list.mutex);
@@ -645,11 +640,10 @@ struct vhost_user_reconnect_list {
 				goto out;
 			}
 		}
-		ret = vhost_user_create_client(vsocket);
 	} else {
 		vsocket->is_server = true;
-		ret = vhost_user_create_server(vsocket);
 	}
+	ret = create_unix_socket(vsocket);
 	if (ret < 0) {
 		free(vsocket->path);
 		free(vsocket);
@@ -705,8 +699,8 @@ struct vhost_user_reconnect_list {
 
 		if (!strcmp(vsocket->path, path)) {
 			if (vsocket->is_server) {
-				fdset_del(&vhost_user.fdset, vsocket->listenfd);
-				close(vsocket->listenfd);
+				fdset_del(&vhost_user.fdset, vsocket->socket_fd);
+				close(vsocket->socket_fd);
 				unlink(path);
 			} else if (vsocket->reconnect) {
 				vhost_user_remove_reconnect(vsocket);
@@ -776,8 +770,28 @@ struct vhost_device_ops const *
 }
 
 int
-rte_vhost_driver_session_start(void)
+rte_vhost_driver_start(const char *path)
 {
-	fdset_event_dispatch(&vhost_user.fdset);
-	return 0;
+	struct vhost_user_socket *vsocket;
+	static pthread_t fdset_tid;
+
+	pthread_mutex_lock(&vhost_user.mutex);
+	vsocket = find_vhost_user_socket(path);
+	pthread_mutex_unlock(&vhost_user.mutex);
+
+	if (!vsocket)
+		return -1;
+
+	if (fdset_tid == 0) {
+		int ret = pthread_create(&fdset_tid, NULL, fdset_event_dispatch,
+				     &vhost_user.fdset);
+		if (ret < 0)
+			RTE_LOG(ERR, VHOST_CONFIG,
+				"failed to create fdset handling thread");
+	}
+
+	if (vsocket->is_server)
+		return vhost_user_start_server(vsocket);
+	else
+		return vhost_user_start_client(vsocket);
 }
-- 
1.9.0

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

* [PATCH v4 19/22] vhost: rename header file
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (17 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-05  0:26         ` Thomas Monjalon
  2017-04-01  7:22       ` [PATCH v4 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
                         ` (3 subsequent siblings)
  22 siblings, 1 reply; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
net specific.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 doc/guides/rel_notes/deprecation.rst   |   9 -
 doc/guides/rel_notes/release_17_05.rst |   3 +
 drivers/net/vhost/rte_eth_vhost.c      |   2 +-
 drivers/net/vhost/rte_eth_vhost.h      |   2 +-
 examples/tep_termination/main.c        |   2 +-
 examples/tep_termination/vxlan_setup.c |   2 +-
 examples/vhost/main.c                  |   2 +-
 lib/librte_vhost/Makefile              |   2 +-
 lib/librte_vhost/rte_vhost.h           | 425 +++++++++++++++++++++++++++++++++
 lib/librte_vhost/rte_virtio_net.h      | 425 ---------------------------------
 lib/librte_vhost/vhost.c               |   2 +-
 lib/librte_vhost/vhost.h               |   2 +-
 lib/librte_vhost/vhost_user.h          |   2 +-
 lib/librte_vhost/virtio_net.c          |   2 +-
 14 files changed, 438 insertions(+), 444 deletions(-)
 create mode 100644 lib/librte_vhost/rte_vhost.h
 delete mode 100644 lib/librte_vhost/rte_virtio_net.h

diff --git a/doc/guides/rel_notes/deprecation.rst b/doc/guides/rel_notes/deprecation.rst
index d6544ed..9708b39 100644
--- a/doc/guides/rel_notes/deprecation.rst
+++ b/doc/guides/rel_notes/deprecation.rst
@@ -95,15 +95,6 @@ Deprecation Notices
   Target release for removal of the legacy API will be defined once most
   PMDs have switched to rte_flow.
 
-* vhost: API/ABI changes are planned for 17.05, for making DPDK vhost library
-  generic enough so that applications can build different vhost-user drivers
-  (instead of vhost-user net only) on top of that.
-  Specifically, ``virtio_net_device_ops`` will be renamed to ``vhost_device_ops``.
-  Correspondingly, some API's parameter need be changed. Few more functions also
-  need be reworked to let it be device aware. For example, different virtio device
-  has different feature set, meaning functions like ``rte_vhost_feature_disable``
-  need be changed. Last, file rte_virtio_net.h will be renamed to rte_vhost.h.
-
 * ABI changes are planned for 17.05 in the ``rte_cryptodev_ops`` structure.
   A pointer to a rte_cryptodev_config structure will be added to the
   function prototype ``cryptodev_configure_t``, as a new parameter.
diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst
index ed206d2..ab83098 100644
--- a/doc/guides/rel_notes/release_17_05.rst
+++ b/doc/guides/rel_notes/release_17_05.rst
@@ -231,6 +231,9 @@ API Changes
     ``rte_vhost_driver_start`` should be used, and no need to create a
     thread to call it.
 
+  * The vhost public header file ``rte_virtio_net.h`` is renamed to
+    ``rte_vhost.h``
+
 
 ABI Changes
 -----------
diff --git a/drivers/net/vhost/rte_eth_vhost.c b/drivers/net/vhost/rte_eth_vhost.c
index 0a4c476..a4a35be 100644
--- a/drivers/net/vhost/rte_eth_vhost.c
+++ b/drivers/net/vhost/rte_eth_vhost.c
@@ -40,7 +40,7 @@
 #include <rte_memcpy.h>
 #include <rte_vdev.h>
 #include <rte_kvargs.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_spinlock.h>
 
 #include "rte_eth_vhost.h"
diff --git a/drivers/net/vhost/rte_eth_vhost.h b/drivers/net/vhost/rte_eth_vhost.h
index ea4bce4..39ca771 100644
--- a/drivers/net/vhost/rte_eth_vhost.h
+++ b/drivers/net/vhost/rte_eth_vhost.h
@@ -41,7 +41,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 /*
  * Event description.
diff --git a/examples/tep_termination/main.c b/examples/tep_termination/main.c
index 24c62cd..cd6e3f1 100644
--- a/examples/tep_termination/main.c
+++ b/examples/tep_termination/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "main.h"
 #include "vxlan.h"
diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c
index 8f1f15b..87de74d 100644
--- a/examples/tep_termination/vxlan_setup.c
+++ b/examples/tep_termination/vxlan_setup.c
@@ -49,7 +49,7 @@
 #include <rte_tcp.h>
 
 #include "main.h"
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 #include "vxlan.h"
 #include "vxlan_setup.h"
 
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 64b3eea..08b82f6 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -49,7 +49,7 @@
 #include <rte_log.h>
 #include <rte_string_fns.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_ip.h>
 #include <rte_tcp.h>
 
diff --git a/lib/librte_vhost/Makefile b/lib/librte_vhost/Makefile
index 1262dcc..4a116fe 100644
--- a/lib/librte_vhost/Makefile
+++ b/lib/librte_vhost/Makefile
@@ -51,6 +51,6 @@ SRCS-$(CONFIG_RTE_LIBRTE_VHOST) := fd_man.c socket.c vhost.c vhost_user.c \
 				   virtio_net.c
 
 # install includes
-SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_virtio_net.h
+SYMLINK-$(CONFIG_RTE_LIBRTE_VHOST)-include += rte_vhost.h
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
new file mode 100644
index 0000000..6681dd7
--- /dev/null
+++ b/lib/librte_vhost/rte_vhost.h
@@ -0,0 +1,425 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _RTE_VHOST_H_
+#define _RTE_VHOST_H_
+
+/**
+ * @file
+ * Interface to vhost-user
+ */
+
+#include <stdint.h>
+#include <linux/vhost.h>
+#include <linux/virtio_ring.h>
+#include <sys/eventfd.h>
+
+#include <rte_memory.h>
+#include <rte_mempool.h>
+
+#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
+#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
+#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
+
+/**
+ * Information relating to memory regions including offsets to
+ * addresses in QEMUs memory file.
+ */
+struct rte_vhost_mem_region {
+	uint64_t guest_phys_addr;
+	uint64_t guest_user_addr;
+	uint64_t host_user_addr;
+	uint64_t size;
+	void	 *mmap_addr;
+	uint64_t mmap_size;
+	int fd;
+};
+
+/**
+ * Memory structure includes region and mapping information.
+ */
+struct rte_vhost_memory {
+	uint32_t nregions;
+	struct rte_vhost_mem_region regions[0];
+};
+
+struct rte_vhost_vring {
+	struct vring_desc	*desc;
+	struct vring_avail	*avail;
+	struct vring_used	*used;
+	uint64_t		log_guest_addr;
+
+	int			callfd;
+	int			kickfd;
+	uint16_t		size;
+};
+
+/**
+ * Device and vring operations.
+ */
+struct vhost_device_ops {
+	int (*new_device)(int vid);		/**< Add device. */
+	void (*destroy_device)(int vid);	/**< Remove device. */
+
+	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
+
+	/**
+	 * Features could be changed after the feature negotiation.
+	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
+	 * start/end of live migration, respectively. This callback
+	 * is used to inform the application on such change.
+	 */
+	int (*features_changed)(int vid, uint64_t features);
+
+	void *reserved[4]; /**< Reserved for future extension */
+};
+
+/**
+ * Convert guest physical address to host virtual address
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static inline uint64_t __attribute__((always_inline))
+rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
+{
+	struct rte_vhost_mem_region *reg;
+	uint32_t i;
+
+	for (i = 0; i < mem->nregions; i++) {
+		reg = &mem->regions[i];
+		if (gpa >= reg->guest_phys_addr &&
+		    gpa <  reg->guest_phys_addr + reg->size) {
+			return gpa - reg->guest_phys_addr +
+			       reg->host_user_addr;
+		}
+	}
+
+	return 0;
+}
+
+#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
+
+/**
+ * Log the memory write start with given address.
+ *
+ * This function only need be invoked when the live migration starts.
+ * Therefore, we won't need call it at all in the most of time. For
+ * making the performance impact be minimum, it's suggested to do a
+ * check before calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_write(vid, addr, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param addr
+ *  the starting address for write
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
+
+/**
+ * Log the used ring update start at given offset.
+ *
+ * Same as rte_vhost_log_write, it's suggested to do a check before
+ * calling it:
+ *
+ *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
+ *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  the vring index
+ * @param offset
+ *  the offset inside the used ring
+ * @param len
+ *  the length to write
+ */
+void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
+			      uint64_t offset, uint64_t len);
+
+int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
+
+/**
+ * Register vhost driver. path could be different for multiple
+ * instance support.
+ */
+int rte_vhost_driver_register(const char *path, uint64_t flags);
+
+/* Unregister vhost driver. This is only meaningful to vhost user. */
+int rte_vhost_driver_unregister(const char *path);
+
+/**
+ * Set the feature bits the vhost-user driver supports.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_set_features(const char *path, uint64_t features);
+
+/**
+ * Enable vhost-user driver features.
+ *
+ * Note that
+ * - the param @features should be a subset of the feature bits provided
+ *   by rte_vhost_driver_set_features().
+ * - it must be invoked before vhost-user negotiation starts.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to enable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_enable_features(const char *path, uint64_t features);
+
+/**
+ * Disable vhost-user driver features.
+ *
+ * The two notes at rte_vhost_driver_enable_features() also apply here.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  Features to disable
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_disable_features(const char *path, uint64_t features);
+
+/**
+ * Get the feature bits before feature negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @param features
+ *  A pointer to store the queried feature bits
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_get_features(const char *path, uint64_t *features);
+
+/**
+ * Get the feature bits after negotiation
+ *
+ * @param vid
+ *  Vhost device ID
+ * @param features
+ *  A pointer to store the queried feature bits
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_negotiated_features(int vid, uint64_t *features);
+
+/* Register callbacks. */
+int rte_vhost_driver_callback_register(const char *path,
+	struct vhost_device_ops const * const ops);
+
+/**
+ *
+ * Start the vhost-user driver.
+ *
+ * This function triggers the vhost-user negotiation.
+ *
+ * @param path
+ *  The vhost-user socket file path
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_driver_start(const char *path);
+
+/**
+ * Get the MTU value of the device if set in QEMU.
+ *
+ * @param vid
+ *  virtio-net device ID
+ * @param mtu
+ *  The variable to store the MTU value
+ *
+ * @return
+ *  0: success
+ *  -EAGAIN: device not yet started
+ *  -ENOTSUP: device does not support MTU feature
+ */
+int rte_vhost_get_mtu(int vid, uint16_t *mtu);
+
+/**
+ * Get the numa node from which the virtio net device's memory
+ * is allocated.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The numa node, -1 on failure
+ */
+int rte_vhost_get_numa_node(int vid);
+
+/**
+ * @deprecated
+ * Get the number of queues the device supports.
+ *
+ * Note this function is deprecated, as it returns a queue pair number,
+ * which is vhost specific. Instead, rte_vhost_get_vring_num should
+ * be used.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of queues, 0 on failure
+ */
+__rte_deprecated
+uint32_t rte_vhost_get_queue_num(int vid);
+
+/**
+ * Get the number of vrings the device supports.
+ *
+ * @param vid
+ *  vhost device ID
+ *
+ * @return
+ *  The number of vrings, 0 on failure
+ */
+uint16_t rte_vhost_get_vring_num(int vid);
+
+/**
+ * Get the virtio net device's ifname, which is the vhost-user socket
+ * file path.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param buf
+ *  The buffer to stored the queried ifname
+ * @param len
+ *  The length of buf
+ *
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_ifname(int vid, char *buf, size_t len);
+
+/**
+ * Get how many avail entries are left in the queue
+ *
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index
+ *
+ * @return
+ *  num of avail entires left
+ */
+uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
+
+/**
+ * This function adds buffers to the virtio devices RX virtqueue. Buffers can
+ * be received from the physical port or from another virtual device. A packet
+ * count is returned to indicate the number of packets that were succesfully
+ * added to the RX queue.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param pkts
+ *  array to contain packets to be enqueued
+ * @param count
+ *  packets num to be enqueued
+ * @return
+ *  num of packets enqueued
+ */
+uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
+	struct rte_mbuf **pkts, uint16_t count);
+
+/**
+ * This function gets guest buffers from the virtio device TX virtqueue,
+ * construct host mbufs, copies guest buffer content to host mbufs and
+ * store them in pkts to be processed.
+ * @param vid
+ *  vhost device ID
+ * @param queue_id
+ *  virtio queue index in mq case
+ * @param mbuf_pool
+ *  mbuf_pool where host mbuf is allocated.
+ * @param pkts
+ *  array to contain packets to be dequeued
+ * @param count
+ *  packets num to be dequeued
+ * @return
+ *  num of packets dequeued
+ */
+uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
+
+/**
+ * Get guest mem table: a list of memory regions.
+ *
+ * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
+ * guest memory regions. Application should free it at destroy_device()
+ * callback.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param mem
+ *  To store the returned mem regions
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
+
+/**
+ * Get guest vring info, including the vring address, vring size, etc.
+ *
+ * @param vid
+ *  vhost device ID
+ * @param vring_idx
+ *  vring index
+ * @param vring
+ *  the structure to hold the requested vring info
+ * @return
+ *  0 on success, -1 on failure
+ */
+int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
+			      struct rte_vhost_vring *vring);
+
+#endif /* _RTE_VHOST_H_ */
diff --git a/lib/librte_vhost/rte_virtio_net.h b/lib/librte_vhost/rte_virtio_net.h
deleted file mode 100644
index 890f4b2..0000000
--- a/lib/librte_vhost/rte_virtio_net.h
+++ /dev/null
@@ -1,425 +0,0 @@
-/*-
- *   BSD LICENSE
- *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
- *   All rights reserved.
- *
- *   Redistribution and use in source and binary forms, with or without
- *   modification, are permitted provided that the following conditions
- *   are met:
- *
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in
- *       the documentation and/or other materials provided with the
- *       distribution.
- *     * Neither the name of Intel Corporation nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
- *
- *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _VIRTIO_NET_H_
-#define _VIRTIO_NET_H_
-
-/**
- * @file
- * Interface to vhost net
- */
-
-#include <stdint.h>
-#include <linux/vhost.h>
-#include <linux/virtio_ring.h>
-#include <sys/eventfd.h>
-
-#include <rte_memory.h>
-#include <rte_mempool.h>
-
-#define RTE_VHOST_USER_CLIENT		(1ULL << 0)
-#define RTE_VHOST_USER_NO_RECONNECT	(1ULL << 1)
-#define RTE_VHOST_USER_DEQUEUE_ZERO_COPY	(1ULL << 2)
-
-/**
- * Information relating to memory regions including offsets to
- * addresses in QEMUs memory file.
- */
-struct rte_vhost_mem_region {
-	uint64_t guest_phys_addr;
-	uint64_t guest_user_addr;
-	uint64_t host_user_addr;
-	uint64_t size;
-	void	 *mmap_addr;
-	uint64_t mmap_size;
-	int fd;
-};
-
-/**
- * Memory structure includes region and mapping information.
- */
-struct rte_vhost_memory {
-	uint32_t nregions;
-	struct rte_vhost_mem_region regions[0];
-};
-
-struct rte_vhost_vring {
-	struct vring_desc	*desc;
-	struct vring_avail	*avail;
-	struct vring_used	*used;
-	uint64_t		log_guest_addr;
-
-	int			callfd;
-	int			kickfd;
-	uint16_t		size;
-};
-
-/**
- * Device and vring operations.
- */
-struct vhost_device_ops {
-	int (*new_device)(int vid);		/**< Add device. */
-	void (*destroy_device)(int vid);	/**< Remove device. */
-
-	int (*vring_state_changed)(int vid, uint16_t queue_id, int enable);	/**< triggered when a vring is enabled or disabled */
-
-	/**
-	 * Features could be changed after the feature negotiation.
-	 * For example, VHOST_F_LOG_ALL will be set/cleared at the
-	 * start/end of live migration, respectively. This callback
-	 * is used to inform the application on such change.
-	 */
-	int (*features_changed)(int vid, uint64_t features);
-
-	void *reserved[4]; /**< Reserved for future extension */
-};
-
-/**
- * Convert guest physical address to host virtual address
- *
- * @param mem
- *  the guest memory regions
- * @param gpa
- *  the guest physical address for querying
- * @return
- *  the host virtual address on success, 0 on failure
- */
-static inline uint64_t __attribute__((always_inline))
-rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
-{
-	struct rte_vhost_mem_region *reg;
-	uint32_t i;
-
-	for (i = 0; i < mem->nregions; i++) {
-		reg = &mem->regions[i];
-		if (gpa >= reg->guest_phys_addr &&
-		    gpa <  reg->guest_phys_addr + reg->size) {
-			return gpa - reg->guest_phys_addr +
-			       reg->host_user_addr;
-		}
-	}
-
-	return 0;
-}
-
-#define RTE_VHOST_NEED_LOG(features)	((features) & (1ULL << VHOST_F_LOG_ALL))
-
-/**
- * Log the memory write start with given address.
- *
- * This function only need be invoked when the live migration starts.
- * Therefore, we won't need call it at all in the most of time. For
- * making the performance impact be minimum, it's suggested to do a
- * check before calling it:
- *
- *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
- *                rte_vhost_log_write(vid, addr, len);
- *
- * @param vid
- *  vhost device ID
- * @param addr
- *  the starting address for write
- * @param len
- *  the length to write
- */
-void rte_vhost_log_write(int vid, uint64_t addr, uint64_t len);
-
-/**
- * Log the used ring update start at given offset.
- *
- * Same as rte_vhost_log_write, it's suggested to do a check before
- * calling it:
- *
- *        if (unlikely(RTE_VHOST_NEED_LOG(features)))
- *                rte_vhost_log_used_vring(vid, vring_idx, offset, len);
- *
- * @param vid
- *  vhost device ID
- * @param vring_idx
- *  the vring index
- * @param offset
- *  the offset inside the used ring
- * @param len
- *  the length to write
- */
-void rte_vhost_log_used_vring(int vid, uint16_t vring_idx,
-			      uint64_t offset, uint64_t len);
-
-int rte_vhost_enable_guest_notification(int vid, uint16_t queue_id, int enable);
-
-/**
- * Register vhost driver. path could be different for multiple
- * instance support.
- */
-int rte_vhost_driver_register(const char *path, uint64_t flags);
-
-/* Unregister vhost driver. This is only meaningful to vhost user. */
-int rte_vhost_driver_unregister(const char *path);
-
-/**
- * Set the feature bits the vhost-user driver supports.
- *
- * @param path
- *  The vhost-user socket file path
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_set_features(const char *path, uint64_t features);
-
-/**
- * Enable vhost-user driver features.
- *
- * Note that
- * - the param @features should be a subset of the feature bits provided
- *   by rte_vhost_driver_set_features().
- * - it must be invoked before vhost-user negotiation starts.
- *
- * @param path
- *  The vhost-user socket file path
- * @param features
- *  Features to enable
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_enable_features(const char *path, uint64_t features);
-
-/**
- * Disable vhost-user driver features.
- *
- * The two notes at rte_vhost_driver_enable_features() also apply here.
- *
- * @param path
- *  The vhost-user socket file path
- * @param features
- *  Features to disable
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_disable_features(const char *path, uint64_t features);
-
-/**
- * Get the feature bits before feature negotiation.
- *
- * @param path
- *  The vhost-user socket file path
- * @param features
- *  A pointer to store the queried feature bits
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_get_features(const char *path, uint64_t *features);
-
-/**
- * Get the feature bits after negotiation
- *
- * @param vid
- *  Vhost device ID
- * @param features
- *  A pointer to store the queried feature bits
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_negotiated_features(int vid, uint64_t *features);
-
-/* Register callbacks. */
-int rte_vhost_driver_callback_register(const char *path,
-	struct vhost_device_ops const * const ops);
-
-/**
- *
- * Start the vhost-user driver.
- *
- * This function triggers the vhost-user negotiation.
- *
- * @param path
- *  The vhost-user socket file path
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_driver_start(const char *path);
-
-/**
- * Get the MTU value of the device if set in QEMU.
- *
- * @param vid
- *  virtio-net device ID
- * @param mtu
- *  The variable to store the MTU value
- *
- * @return
- *  0: success
- *  -EAGAIN: device not yet started
- *  -ENOTSUP: device does not support MTU feature
- */
-int rte_vhost_get_mtu(int vid, uint16_t *mtu);
-
-/**
- * Get the numa node from which the virtio net device's memory
- * is allocated.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The numa node, -1 on failure
- */
-int rte_vhost_get_numa_node(int vid);
-
-/**
- * @deprecated
- * Get the number of queues the device supports.
- *
- * Note this function is deprecated, as it returns a queue pair number,
- * which is vhost specific. Instead, rte_vhost_get_vring_num should
- * be used.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of queues, 0 on failure
- */
-__rte_deprecated
-uint32_t rte_vhost_get_queue_num(int vid);
-
-/**
- * Get the number of vrings the device supports.
- *
- * @param vid
- *  vhost device ID
- *
- * @return
- *  The number of vrings, 0 on failure
- */
-uint16_t rte_vhost_get_vring_num(int vid);
-
-/**
- * Get the virtio net device's ifname, which is the vhost-user socket
- * file path.
- *
- * @param vid
- *  vhost device ID
- * @param buf
- *  The buffer to stored the queried ifname
- * @param len
- *  The length of buf
- *
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_ifname(int vid, char *buf, size_t len);
-
-/**
- * Get how many avail entries are left in the queue
- *
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index
- *
- * @return
- *  num of avail entires left
- */
-uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
-
-/**
- * This function adds buffers to the virtio devices RX virtqueue. Buffers can
- * be received from the physical port or from another virtual device. A packet
- * count is returned to indicate the number of packets that were succesfully
- * added to the RX queue.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param pkts
- *  array to contain packets to be enqueued
- * @param count
- *  packets num to be enqueued
- * @return
- *  num of packets enqueued
- */
-uint16_t rte_vhost_enqueue_burst(int vid, uint16_t queue_id,
-	struct rte_mbuf **pkts, uint16_t count);
-
-/**
- * This function gets guest buffers from the virtio device TX virtqueue,
- * construct host mbufs, copies guest buffer content to host mbufs and
- * store them in pkts to be processed.
- * @param vid
- *  vhost device ID
- * @param queue_id
- *  virtio queue index in mq case
- * @param mbuf_pool
- *  mbuf_pool where host mbuf is allocated.
- * @param pkts
- *  array to contain packets to be dequeued
- * @param count
- *  packets num to be dequeued
- * @return
- *  num of packets dequeued
- */
-uint16_t rte_vhost_dequeue_burst(int vid, uint16_t queue_id,
-	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count);
-
-/**
- * Get guest mem table: a list of memory regions.
- *
- * An rte_vhost_vhost_memory object will be allocated internaly, to hold the
- * guest memory regions. Application should free it at destroy_device()
- * callback.
- *
- * @param vid
- *  vhost device ID
- * @param mem
- *  To store the returned mem regions
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_mem_table(int vid, struct rte_vhost_memory **mem);
-
-/**
- * Get guest vring info, including the vring address, vring size, etc.
- *
- * @param vid
- *  vhost device ID
- * @param vring_idx
- *  vring index
- * @param vring
- *  the structure to hold the requested vring info
- * @return
- *  0 on success, -1 on failure
- */
-int rte_vhost_get_vhost_vring(int vid, uint16_t vring_idx,
-			      struct rte_vhost_vring *vring);
-
-#endif /* _VIRTIO_NET_H_ */
diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c
index 59de2ea..0b19d2e 100644
--- a/lib/librte_vhost/vhost.c
+++ b/lib/librte_vhost/vhost.c
@@ -45,7 +45,7 @@
 #include <rte_string_fns.h>
 #include <rte_memory.h>
 #include <rte_malloc.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 
 #include "vhost.h"
 
diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h
index a199ee6..ddd8a9c 100644
--- a/lib/librte_vhost/vhost.h
+++ b/lib/librte_vhost/vhost.h
@@ -46,7 +46,7 @@
 #include <rte_log.h>
 #include <rte_ether.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* Used to indicate that the device is running on a data core */
 #define VIRTIO_DEV_RUNNING 1
diff --git a/lib/librte_vhost/vhost_user.h b/lib/librte_vhost/vhost_user.h
index 838dec8..2ba22db 100644
--- a/lib/librte_vhost/vhost_user.h
+++ b/lib/librte_vhost/vhost_user.h
@@ -37,7 +37,7 @@
 #include <stdint.h>
 #include <linux/vhost.h>
 
-#include "rte_virtio_net.h"
+#include "rte_vhost.h"
 
 /* refer to hw/virtio/vhost-user.c */
 
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index fc336d9..d6b7c7a 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -39,7 +39,7 @@
 #include <rte_memcpy.h>
 #include <rte_ether.h>
 #include <rte_ip.h>
-#include <rte_virtio_net.h>
+#include <rte_vhost.h>
 #include <rte_tcp.h>
 #include <rte_udp.h>
 #include <rte_sctp.h>
-- 
1.9.0

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

* [PATCH v4 20/22] vhost: workaround the build dependency on mbuf header
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (18 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 19/22] vhost: rename header file Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:22       ` [PATCH v4 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
                         ` (2 subsequent siblings)
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

rte_mbuf struct is something more likely will be used only in vhost-user
net driver, while we have made vhost-user generic enough that it can
be used for implementing other drivers (such as vhost-user SCSI), they
have also include <rte_mbuf.h>. Otherwise, the build will be broken.

We could workaround it by using forward declaration, so that other
non-net drivers won't need include <rte_mbuf.h>.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/rte_vhost.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/librte_vhost/rte_vhost.h b/lib/librte_vhost/rte_vhost.h
index 6681dd7..5fb9dfb 100644
--- a/lib/librte_vhost/rte_vhost.h
+++ b/lib/librte_vhost/rte_vhost.h
@@ -352,6 +352,8 @@ int rte_vhost_driver_callback_register(const char *path,
  */
 uint16_t rte_vhost_avail_entries(int vid, uint16_t queue_id);
 
+struct rte_mbuf;
+struct rte_mempool;
 /**
  * This function adds buffers to the virtio devices RX virtqueue. Buffers can
  * be received from the physical port or from another virtual device. A packet
-- 
1.9.0

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

* [PATCH v4 21/22] vhost: do not destroy device on repeat mem table message
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (19 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
@ 2017-04-01  7:22       ` Yuanhan Liu
  2017-04-01  7:23       ` [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
  2017-04-01  8:44       ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:22 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

It doesn't make any sense to invoke destroy_device() callback at
while handling SET_MEM_TABLE message.

>From the vhost-user spec, it's the GET_VRING_BASE message indicates
the end of a vhost device: the destroy_device() should be invoked
from there (luckily, we already did that).

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
 lib/librte_vhost/vhost_user.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index bade6ad..6cafb75 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -502,12 +502,6 @@
 	uint32_t i;
 	int fd;
 
-	/* Remove from the data plane. */
-	if (dev->flags & VIRTIO_DEV_RUNNING) {
-		dev->flags &= ~VIRTIO_DEV_RUNNING;
-		dev->notify_ops->destroy_device(dev->vid);
-	}
-
 	if (dev->mem) {
 		free_mem_region(dev);
 		rte_free(dev->mem);
-- 
1.9.0

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

* [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (20 preceding siblings ...)
  2017-04-01  7:22       ` [PATCH v4 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
@ 2017-04-01  7:23       ` Yuanhan Liu
  2017-04-01  8:44       ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  7:23 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng, Yuanhan Liu

Now DPDK vhost lib has been generic enough, that it can be used to
implement any vhost-user drivers.

For example, this patch implements a very simple vhost-user net driver,
mainly for demonstrating how to use those generic vhost APIs.

And when the --builtin-net-driver option is used, the example virtio-net
driver code will be invoked, instead of the one provided from the vhost
library.

Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
---
 examples/vhost/Makefile     |   2 +-
 examples/vhost/main.c       |  37 +++-
 examples/vhost/main.h       |  28 ++-
 examples/vhost/virtio_net.c | 405 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 465 insertions(+), 7 deletions(-)
 create mode 100644 examples/vhost/virtio_net.c

diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile
index e95c68a..af7be99 100644
--- a/examples/vhost/Makefile
+++ b/examples/vhost/Makefile
@@ -48,7 +48,7 @@ else
 APP = vhost-switch
 
 # all source are stored in SRCS-y
-SRCS-y := main.c
+SRCS-y := main.c virtio_net.c
 
 CFLAGS += -O2 -D_FILE_OFFSET_BITS=64
 CFLAGS += $(WERROR_FLAGS)
diff --git a/examples/vhost/main.c b/examples/vhost/main.c
index 08b82f6..022438e 100644
--- a/examples/vhost/main.c
+++ b/examples/vhost/main.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,6 @@
 #define MBUF_CACHE_SIZE	128
 #define MBUF_DATA_SIZE	RTE_MBUF_DEFAULT_BUF_SIZE
 
-#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
 #define BURST_TX_DRAIN_US 100	/* TX drain every ~100us */
 
 #define BURST_RX_WAIT_US 15	/* Defines how long we wait between retries on RX */
@@ -129,6 +128,8 @@
 static int client_mode;
 static int dequeue_zero_copy;
 
+static int builtin_net_driver;
+
 /* Specify timeout (in useconds) between retries on RX. */
 static uint32_t burst_rx_delay_time = BURST_RX_WAIT_US;
 /* Specify the number of retries on RX. */
@@ -499,6 +500,7 @@ struct mbuf_table {
 		{"tso", required_argument, NULL, 0},
 		{"client", no_argument, &client_mode, 1},
 		{"dequeue-zero-copy", no_argument, &dequeue_zero_copy, 1},
+		{"builtin-net-driver", no_argument, &builtin_net_driver, 1},
 		{NULL, 0, 0, 0},
 	};
 
@@ -795,7 +797,12 @@ static inline void __attribute__((always_inline))
 {
 	uint16_t ret;
 
-	ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	if (builtin_net_driver) {
+		ret = vs_enqueue_pkts(dst_vdev, VIRTIO_RXQ, &m, 1);
+	} else {
+		ret = rte_vhost_enqueue_burst(dst_vdev->vid, VIRTIO_RXQ, &m, 1);
+	}
+
 	if (enable_stats) {
 		rte_atomic64_inc(&dst_vdev->stats.rx_total_atomic);
 		rte_atomic64_add(&dst_vdev->stats.rx_atomic, ret);
@@ -1066,8 +1073,13 @@ static inline void __attribute__((always_inline))
 		}
 	}
 
-	enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+	if (builtin_net_driver) {
+		enqueue_count = vs_enqueue_pkts(vdev, VIRTIO_RXQ,
 						pkts, rx_count);
+	} else {
+		enqueue_count = rte_vhost_enqueue_burst(vdev->vid, VIRTIO_RXQ,
+						pkts, rx_count);
+	}
 	if (enable_stats) {
 		rte_atomic64_add(&vdev->stats.rx_total_atomic, rx_count);
 		rte_atomic64_add(&vdev->stats.rx_atomic, enqueue_count);
@@ -1083,8 +1095,13 @@ static inline void __attribute__((always_inline))
 	uint16_t count;
 	uint16_t i;
 
-	count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, mbuf_pool,
+	if (builtin_net_driver) {
+		count = vs_dequeue_pkts(vdev, VIRTIO_TXQ, mbuf_pool,
 					pkts, MAX_PKT_BURST);
+	} else {
+		count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ,
+					mbuf_pool, pkts, MAX_PKT_BURST);
+	}
 
 	/* setup VMDq for the first packet */
 	if (unlikely(vdev->ready == DEVICE_MAC_LEARNING) && count) {
@@ -1187,6 +1204,9 @@ static inline void __attribute__((always_inline))
 		rte_pause();
 	}
 
+	if (builtin_net_driver)
+		vs_vhost_net_remove(vdev);
+
 	TAILQ_REMOVE(&lcore_info[vdev->coreid].vdev_list, vdev,
 		     lcore_vdev_entry);
 	TAILQ_REMOVE(&vhost_dev_list, vdev, global_vdev_entry);
@@ -1235,6 +1255,9 @@ static inline void __attribute__((always_inline))
 	}
 	vdev->vid = vid;
 
+	if (builtin_net_driver)
+		vs_vhost_net_setup(vdev);
+
 	TAILQ_INSERT_TAIL(&vhost_dev_list, vdev, global_vdev_entry);
 	vdev->vmdq_rx_q = vid * queues_per_pool + vmdq_queue_base;
 
@@ -1513,6 +1536,10 @@ static inline void __attribute__((always_inline))
 			rte_exit(EXIT_FAILURE,
 				"vhost driver register failure.\n");
 		}
+
+		if (builtin_net_driver)
+			rte_vhost_driver_set_features(file, VIRTIO_NET_FEATURES);
+
 		if (mergeable == 0) {
 			rte_vhost_driver_disable_features(file,
 				1ULL << VIRTIO_NET_F_MRG_RXBUF);
diff --git a/examples/vhost/main.h b/examples/vhost/main.h
index ddcd858..9a2aca3 100644
--- a/examples/vhost/main.h
+++ b/examples/vhost/main.h
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -45,6 +45,8 @@
 
 enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM};
 
+#define MAX_PKT_BURST 32		/* Max burst size for RX/TX */
+
 struct device_statistics {
 	uint64_t	tx;
 	uint64_t	tx_total;
@@ -52,6 +54,12 @@ struct device_statistics {
 	rte_atomic64_t	rx_total_atomic;
 };
 
+struct vhost_queue {
+	struct rte_vhost_vring	vr;
+	uint16_t		last_avail_idx;
+	uint16_t		last_used_idx;
+};
+
 struct vhost_dev {
 	/**< Number of memory regions for gpa to hpa translation. */
 	uint32_t nregions_hpa;
@@ -69,9 +77,16 @@ struct vhost_dev {
 	volatile uint8_t remove;
 
 	int vid;
+	uint64_t features;
+	size_t hdr_len;
+	uint16_t nr_vrings;
+	struct rte_vhost_memory *mem;
 	struct device_statistics stats;
 	TAILQ_ENTRY(vhost_dev) global_vdev_entry;
 	TAILQ_ENTRY(vhost_dev) lcore_vdev_entry;
+
+#define MAX_QUEUE_PAIRS	4
+	struct vhost_queue queues[MAX_QUEUE_PAIRS * 2];
 } __rte_cache_aligned;
 
 TAILQ_HEAD(vhost_dev_tailq_list, vhost_dev);
@@ -92,4 +107,15 @@ struct lcore_info {
 	struct vhost_dev_tailq_list vdev_list;
 };
 
+/* we implement non-extra virtio net features */
+#define VIRTIO_NET_FEATURES	0
+
+void vs_vhost_net_setup(struct vhost_dev *dev);
+void vs_vhost_net_remove(struct vhost_dev *dev);
+uint16_t vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mbuf **pkts, uint32_t count);
+
+uint16_t vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+			 struct rte_mempool *mbuf_pool,
+			 struct rte_mbuf **pkts, uint16_t count);
 #endif /* _MAIN_H_ */
diff --git a/examples/vhost/virtio_net.c b/examples/vhost/virtio_net.c
new file mode 100644
index 0000000..d86dd66
--- /dev/null
+++ b/examples/vhost/virtio_net.c
@@ -0,0 +1,405 @@
+/*-
+ *   BSD LICENSE
+ *
+ *   Copyright(c) 2010-2017 Intel Corporation. All rights reserved.
+ *   All rights reserved.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following conditions
+ *   are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in
+ *       the documentation and/or other materials provided with the
+ *       distribution.
+ *     * Neither the name of Intel Corporation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <linux/virtio_net.h>
+
+#include <rte_mbuf.h>
+#include <rte_memcpy.h>
+#include <rte_vhost.h>
+
+#include "main.h"
+
+/*
+ * A very simple vhost-user net driver implementation, without
+ * any extra features being enabled, such as TSO and mrg-Rx.
+ */
+
+void
+vs_vhost_net_setup(struct vhost_dev *dev)
+{
+	uint16_t i;
+	int vid = dev->vid;
+	struct vhost_queue *queue;
+
+	RTE_LOG(INFO, VHOST_CONFIG,
+		"setting builtin vhost-user net driver\n");
+
+	rte_vhost_get_negotiated_features(vid, &dev->features);
+	if (dev->features &
+		((1 << VIRTIO_NET_F_MRG_RXBUF) | (1ULL << VIRTIO_F_VERSION_1))) {
+		dev->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+	} else {
+		dev->hdr_len = sizeof(struct virtio_net_hdr);
+	}
+
+	rte_vhost_get_mem_table(vid, &dev->mem);
+
+	dev->nr_vrings = rte_vhost_get_vring_num(vid);
+	for (i = 0; i < dev->nr_vrings; i++) {
+		queue = &dev->queues[i];
+
+		queue->last_used_idx  = 0;
+		queue->last_avail_idx = 0;
+		rte_vhost_get_vhost_vring(vid, i, &queue->vr);
+	}
+}
+
+void
+vs_vhost_net_remove(struct vhost_dev *dev)
+{
+	free(dev->mem);
+}
+
+static inline int __attribute__((always_inline))
+enqueue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx)
+{
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	struct virtio_net_hdr virtio_hdr = {0, 0, 0, 0, 0, 0};
+	/* A counter to avoid desc dead loop chain */
+	uint16_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	/*
+	 * Checking of 'desc_addr' placed outside of 'unlikely' macro to avoid
+	 * performance issue with some versions of gcc (4.8.4 and 5.3.0) which
+	 * otherwise stores offset on the stack instead of in a register.
+	 */
+	if (unlikely(desc->len < dev->hdr_len) || !desc_addr)
+		return -1;
+
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	/* write virtio-net header */
+	*(struct virtio_net_hdr *)(uintptr_t)desc_addr = virtio_hdr;
+
+	desc_offset = dev->hdr_len;
+	desc_avail  = desc->len - dev->hdr_len;
+
+	mbuf_avail  = rte_pktmbuf_data_len(m);
+	mbuf_offset = 0;
+	while (mbuf_avail != 0 || m->next != NULL) {
+		/* done with current mbuf, fetch next */
+		if (mbuf_avail == 0) {
+			m = m->next;
+
+			mbuf_offset = 0;
+			mbuf_avail  = rte_pktmbuf_data_len(m);
+		}
+
+		/* done with current desc buf, fetch next */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0) {
+				/* Room in vring buffer is not enough */
+				return -1;
+			}
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+
+			desc = &vr->desc[desc->next];
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy((void *)((uintptr_t)(desc_addr + desc_offset)),
+			rte_pktmbuf_mtod_offset(m, void *, mbuf_offset),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+	}
+
+	return 0;
+}
+
+uint16_t
+vs_enqueue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+		struct rte_mbuf **pkts, uint32_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint16_t avail_idx, free_entries, start_idx;
+	uint16_t desc_indexes[MAX_PKT_BURST];
+	uint16_t used_idx;
+	uint32_t i;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	avail_idx = *((volatile uint16_t *)&vr->avail->idx);
+	start_idx = queue->last_used_idx;
+	free_entries = avail_idx - start_idx;
+	count = RTE_MIN(count, free_entries);
+	count = RTE_MIN(count, (uint32_t)MAX_PKT_BURST);
+	if (count == 0)
+		return 0;
+
+	/* Retrieve all of the desc indexes first to avoid caching issues. */
+	rte_prefetch0(&vr->avail->ring[start_idx & (vr->size - 1)]);
+	for (i = 0; i < count; i++) {
+		used_idx = (start_idx + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[used_idx];
+		vr->used->ring[used_idx].id = desc_indexes[i];
+		vr->used->ring[used_idx].len = pkts[i]->pkt_len +
+					       dev->hdr_len;
+	}
+
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		uint16_t desc_idx = desc_indexes[i];
+		int err;
+
+		err = enqueue_pkt(dev, vr, pkts[i], desc_idx);
+		if (unlikely(err)) {
+			used_idx = (start_idx + i) & (vr->size - 1);
+			vr->used->ring[used_idx].len = dev->hdr_len;
+		}
+
+		if (i + 1 < count)
+			rte_prefetch0(&vr->desc[desc_indexes[i+1]]);
+	}
+
+	rte_smp_wmb();
+
+	*(volatile uint16_t *)&vr->used->idx += count;
+	queue->last_used_idx += count;
+
+	/* flush used->idx update before we read avail->flags. */
+	rte_mb();
+
+	/* Kick the guest if necessary. */
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+	return count;
+}
+
+static inline int __attribute__((always_inline))
+dequeue_pkt(struct vhost_dev *dev, struct rte_vhost_vring *vr,
+	    struct rte_mbuf *m, uint16_t desc_idx,
+	    struct rte_mempool *mbuf_pool)
+{
+	struct vring_desc *desc;
+	uint64_t desc_addr;
+	uint32_t desc_avail, desc_offset;
+	uint32_t mbuf_avail, mbuf_offset;
+	uint32_t cpy_len;
+	struct rte_mbuf *cur = m, *prev = m;
+	/* A counter to avoid desc dead loop chain */
+	uint32_t nr_desc = 1;
+
+	desc = &vr->desc[desc_idx];
+	if (unlikely((desc->len < dev->hdr_len)) ||
+			(desc->flags & VRING_DESC_F_INDIRECT))
+		return -1;
+
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+
+	/*
+	 * We don't support ANY_LAYOUT, neither VERSION_1, meaning
+	 * a Tx packet from guest must have 2 desc buffers at least:
+	 * the first for storing the header and the others for
+	 * storing the data.
+	 *
+	 * And since we don't support TSO, we could simply skip the
+	 * header.
+	 */
+	desc = &vr->desc[desc->next];
+	desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+	if (unlikely(!desc_addr))
+		return -1;
+	rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+	desc_offset = 0;
+	desc_avail  = desc->len;
+	nr_desc    += 1;
+
+	mbuf_offset = 0;
+	mbuf_avail  = m->buf_len - RTE_PKTMBUF_HEADROOM;
+	while (1) {
+		cpy_len = RTE_MIN(desc_avail, mbuf_avail);
+		rte_memcpy(rte_pktmbuf_mtod_offset(cur, void *,
+						   mbuf_offset),
+			(void *)((uintptr_t)(desc_addr + desc_offset)),
+			cpy_len);
+
+		mbuf_avail  -= cpy_len;
+		mbuf_offset += cpy_len;
+		desc_avail  -= cpy_len;
+		desc_offset += cpy_len;
+
+		/* This desc reaches to its end, get the next one */
+		if (desc_avail == 0) {
+			if ((desc->flags & VRING_DESC_F_NEXT) == 0)
+				break;
+
+			if (unlikely(desc->next >= vr->size ||
+				     ++nr_desc > vr->size))
+				return -1;
+			desc = &vr->desc[desc->next];
+
+			desc_addr = rte_vhost_gpa_to_vva(dev->mem, desc->addr);
+			if (unlikely(!desc_addr))
+				return -1;
+			rte_prefetch0((void *)(uintptr_t)desc_addr);
+
+			desc_offset = 0;
+			desc_avail  = desc->len;
+		}
+
+		/*
+		 * This mbuf reaches to its end, get a new one
+		 * to hold more data.
+		 */
+		if (mbuf_avail == 0) {
+			cur = rte_pktmbuf_alloc(mbuf_pool);
+			if (unlikely(cur == NULL)) {
+				RTE_LOG(ERR, VHOST_DATA, "Failed to "
+					"allocate memory for mbuf.\n");
+				return -1;
+			}
+
+			prev->next = cur;
+			prev->data_len = mbuf_offset;
+			m->nb_segs += 1;
+			m->pkt_len += mbuf_offset;
+			prev = cur;
+
+			mbuf_offset = 0;
+			mbuf_avail  = cur->buf_len - RTE_PKTMBUF_HEADROOM;
+		}
+	}
+
+	prev->data_len = mbuf_offset;
+	m->pkt_len    += mbuf_offset;
+
+	return 0;
+}
+
+uint16_t
+vs_dequeue_pkts(struct vhost_dev *dev, uint16_t queue_id,
+	struct rte_mempool *mbuf_pool, struct rte_mbuf **pkts, uint16_t count)
+{
+	struct vhost_queue *queue;
+	struct rte_vhost_vring *vr;
+	uint32_t desc_indexes[MAX_PKT_BURST];
+	uint32_t used_idx;
+	uint32_t i = 0;
+	uint16_t free_entries;
+	uint16_t avail_idx;
+
+	queue = &dev->queues[queue_id];
+	vr    = &queue->vr;
+
+	free_entries = *((volatile uint16_t *)&vr->avail->idx) -
+			queue->last_avail_idx;
+	if (free_entries == 0)
+		return 0;
+
+	/* Prefetch available and used ring */
+	avail_idx = queue->last_avail_idx & (vr->size - 1);
+	used_idx  = queue->last_used_idx  & (vr->size - 1);
+	rte_prefetch0(&vr->avail->ring[avail_idx]);
+	rte_prefetch0(&vr->used->ring[used_idx]);
+
+	count = RTE_MIN(count, MAX_PKT_BURST);
+	count = RTE_MIN(count, free_entries);
+
+	/*
+	 * Retrieve all of the head indexes first and pre-update used entries
+	 * to avoid caching issues.
+	 */
+	for (i = 0; i < count; i++) {
+		avail_idx = (queue->last_avail_idx + i) & (vr->size - 1);
+		used_idx  = (queue->last_used_idx  + i) & (vr->size - 1);
+		desc_indexes[i] = vr->avail->ring[avail_idx];
+
+		vr->used->ring[used_idx].id  = desc_indexes[i];
+		vr->used->ring[used_idx].len = 0;
+	}
+
+	/* Prefetch descriptor index. */
+	rte_prefetch0(&vr->desc[desc_indexes[0]]);
+	for (i = 0; i < count; i++) {
+		int err;
+
+		if (likely(i + 1 < count))
+			rte_prefetch0(&vr->desc[desc_indexes[i + 1]]);
+
+		pkts[i] = rte_pktmbuf_alloc(mbuf_pool);
+		if (unlikely(pkts[i] == NULL)) {
+			RTE_LOG(ERR, VHOST_DATA,
+				"Failed to allocate memory for mbuf.\n");
+			break;
+		}
+
+		err = dequeue_pkt(dev, vr, pkts[i], desc_indexes[i], mbuf_pool);
+		if (unlikely(err)) {
+			rte_pktmbuf_free(pkts[i]);
+			break;
+		}
+
+	}
+	if (!i)
+		return 0;
+
+	queue->last_avail_idx += i;
+	queue->last_used_idx += i;
+	rte_smp_wmb();
+	rte_smp_rmb();
+
+	vr->used->idx += i;
+
+	if (!(vr->avail->flags & VRING_AVAIL_F_NO_INTERRUPT)
+			&& (vr->callfd >= 0))
+		eventfd_write(vr->callfd, (eventfd_t)1);
+
+	return i;
+}
-- 
1.9.0

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

* Re: [PATCH v4 06/22] vhost: introduce API to fetch negotiated features
  2017-04-01  7:22       ` [PATCH v4 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
@ 2017-04-01  8:28         ` Maxime Coquelin
  0 siblings, 0 replies; 135+ messages in thread
From: Maxime Coquelin @ 2017-04-01  8:28 UTC (permalink / raw)
  To: Yuanhan Liu, dev; +Cc: Harris James R, Liu Changpeng



On 04/01/2017 09:22 AM, Yuanhan Liu wrote:
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> ---
>
> v4: use parameter to store the returned features and return -1 on error
> ---
>  lib/librte_vhost/rte_vhost_version.map |  1 +
>  lib/librte_vhost/rte_virtio_net.h      | 12 ++++++++++++
>  lib/librte_vhost/vhost.c               | 13 +++++++++++++
>  3 files changed, 26 insertions(+)


Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>

Thanks!
Maxime

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

* Re: [PATCH v4 00/22] vhost: generic vhost API
  2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
                         ` (21 preceding siblings ...)
  2017-04-01  7:23       ` [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
@ 2017-04-01  8:44       ` Yuanhan Liu
  22 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-01  8:44 UTC (permalink / raw)
  To: dev; +Cc: Maxime Coquelin, Harris James R, Liu Changpeng

On Sat, Apr 01, 2017 at 03:22:38PM +0800, Yuanhan Liu wrote:
> This patchset makes DPDK vhost library generic enough, so that we could
> build other vhost-user drivers on top of it. For example, SPDK (Storage
> Performance Development Kit) is trying to enable vhost-user SCSI.
> 
> The basic idea is, let DPDK vhost be a vhost-user agent. It stores all
> the info about the virtio device (i.e. vring address, negotiated features,
> etc) and let the specific vhost-user driver to fetch them (by the API
> provided by DPDK vhost lib). With those info being provided, the vhost-user
> driver then could get/put vring entries, thus, it could exchange data
> between the guest and host.
> 
> The last patch demonstrates how to use these new APIs to implement a
> very simple vhost-user net driver, without any fancy features enabled.

Series applied to dpdk-next-virtio.

	--yliu
> 
> 
> Change log
> ==========
> 
> v2: - rebase
>     - updated release note
>     - updated API comments
>     - renamed rte_vhost_get_vhost_memory to rte_vhost_get_mem_table
> 
>     - added a new device callback: features_changed(), bascially for live
>       migration support
>     - introduced rte_vhost_driver_start() to start a specific driver
>     - misc fixes
> 
> v3: - rebaseon top of vhost-user socket fix
>     - fix reconnect
>     - fix shared build
>     - fix typos
> 
> v4: - rebase
>     - let rte_vhost_get.*_features() to return features by parameter and
>       return -1 on failure
>     - Follow the style of ring rework to update the release note: use one
>       entry for all vhost changes and add sub items for each change.
> 
> 
> Major API/ABI Changes summary
> =============================
> 
> - some renames
>   * "struct virtio_net_device_ops" ==> "struct vhost_device_ops"
>   * "rte_virtio_net.h"  ==> "rte_vhost.h"
> 
> - driver related APIs are bond with the socket file
>   * rte_vhost_driver_set_features(socket_file, features);
>   * rte_vhost_driver_get_features(socket_file, features);
>   * rte_vhost_driver_enable_features(socket_file, features)
>   * rte_vhost_driver_disable_features(socket_file, features)
>   * rte_vhost_driver_callback_register(socket_file, notify_ops);
>   * rte_vhost_driver_start(socket_file);
>     This function replaces rte_vhost_driver_session_start(). Check patch
>     18 for more information.
> 
> - new APIs to fetch guest and vring info
>   * rte_vhost_get_mem_table(vid, mem);
>   * rte_vhost_get_negotiated_features(vid);
>   * rte_vhost_get_vhost_vring(vid, vring_idx, vring);
> 
> - new exported structures 
>   * struct rte_vhost_vring
>   * struct rte_vhost_mem_region
>   * struct rte_vhost_memory
> 
> - a new device ops callback: features_changed().
> 
> 
> 	--yliu
> 
> ---
> Yuanhan Liu (22):
>   vhost: introduce driver features related APIs
>   net/vhost: remove feature related APIs
>   vhost: use new APIs to handle features
>   vhost: make notify ops per vhost driver
>   vhost: export guest memory regions
>   vhost: introduce API to fetch negotiated features
>   vhost: export vhost vring info
>   vhost: export API to translate gpa to vva
>   vhost: turn queue pair to vring
>   vhost: export the number of vrings
>   vhost: move the device ready check at proper place
>   vhost: drop the Rx and Tx queue macro
>   vhost: do not include net specific headers
>   vhost: rename device ops struct
>   vhost: rename virtio-net to vhost
>   vhost: add features changed callback
>   vhost: export APIs for live migration support
>   vhost: introduce API to start a specific driver
>   vhost: rename header file
>   vhost: workaround the build dependency on mbuf header
>   vhost: do not destroy device on repeat mem table message
>   examples/vhost: demonstrate the new generic vhost APIs
> 
>  doc/guides/prog_guide/vhost_lib.rst         |  42 +--
>  doc/guides/rel_notes/deprecation.rst        |   9 -
>  doc/guides/rel_notes/release_17_05.rst      |  43 +++
>  drivers/net/vhost/rte_eth_vhost.c           | 101 ++-----
>  drivers/net/vhost/rte_eth_vhost.h           |  32 +--
>  drivers/net/vhost/rte_pmd_vhost_version.map |   3 -
>  examples/tep_termination/main.c             |  23 +-
>  examples/tep_termination/main.h             |   2 +
>  examples/tep_termination/vxlan_setup.c      |   2 +-
>  examples/vhost/Makefile                     |   2 +-
>  examples/vhost/main.c                       | 100 +++++--
>  examples/vhost/main.h                       |  32 ++-
>  examples/vhost/virtio_net.c                 | 405 ++++++++++++++++++++++++++
>  lib/librte_vhost/Makefile                   |   4 +-
>  lib/librte_vhost/fd_man.c                   |   9 +-
>  lib/librte_vhost/fd_man.h                   |   2 +-
>  lib/librte_vhost/rte_vhost.h                | 427 ++++++++++++++++++++++++++++
>  lib/librte_vhost/rte_vhost_version.map      |  16 +-
>  lib/librte_vhost/rte_virtio_net.h           | 208 --------------
>  lib/librte_vhost/socket.c                   | 229 ++++++++++++---
>  lib/librte_vhost/vhost.c                    | 230 ++++++++-------
>  lib/librte_vhost/vhost.h                    | 113 +++++---
>  lib/librte_vhost/vhost_user.c               | 121 ++++----
>  lib/librte_vhost/vhost_user.h               |   2 +-
>  lib/librte_vhost/virtio_net.c               |  71 ++---
>  25 files changed, 1541 insertions(+), 687 deletions(-)
>  create mode 100644 examples/vhost/virtio_net.c
>  create mode 100644 lib/librte_vhost/rte_vhost.h
>  delete mode 100644 lib/librte_vhost/rte_virtio_net.h
> 
> -- 
> 1.9.0

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

* Re: [PATCH v4 01/22] vhost: introduce driver features related APIs
  2017-04-01  7:22       ` [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-04-05  0:01         ` Thomas Monjalon
  0 siblings, 0 replies; 135+ messages in thread
From: Thomas Monjalon @ 2017-04-05  0:01 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Maxime Coquelin, Harris James R, Liu Changpeng

2017-04-01 15:22, Yuanhan Liu:
> +/**
> + * Set the feature bits the vhost-user driver supports.
> + *
> + * @param path
> + *  The vhost-user socket file path
> + * @return
> + *  0 on success, -1 on failure
> + */
> +int rte_vhost_driver_set_features(const char *path, uint64_t features);

The parameter @features is not documented.

I suggest
+ * @param features
+ *  Supported features

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

* Re: [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro
  2017-04-01  7:22       ` [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
@ 2017-04-05  0:17         ` Thomas Monjalon
  0 siblings, 0 replies; 135+ messages in thread
From: Thomas Monjalon @ 2017-04-05  0:17 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Maxime Coquelin, Harris James R, Liu Changpeng

2017-04-01 15:22, Yuanhan Liu:
> They are virtio-net specific and should be defined inside the virtio-net
> driver.
> 
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> ---
> 
> v2: - update release note
> ---
>  doc/guides/rel_notes/release_17_05.rst | 6 ++++++
>  drivers/net/vhost/rte_eth_vhost.c      | 2 ++
>  examples/tep_termination/main.h        | 2 ++
>  examples/vhost/main.h                  | 2 ++
>  lib/librte_vhost/rte_virtio_net.h      | 3 ---
>  5 files changed, 12 insertions(+), 3 deletions(-)

The enum is missing in lib/librte_vhost/vhost_user.c when
RTE_LIBRTE_VHOST_NUMA is enabled.

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

* Re: [PATCH v4 19/22] vhost: rename header file
  2017-04-01  7:22       ` [PATCH v4 19/22] vhost: rename header file Yuanhan Liu
@ 2017-04-05  0:26         ` Thomas Monjalon
  2017-04-05  5:16           ` Yuanhan Liu
  0 siblings, 1 reply; 135+ messages in thread
From: Thomas Monjalon @ 2017-04-05  0:26 UTC (permalink / raw)
  To: Yuanhan Liu; +Cc: dev, Maxime Coquelin, Harris James R, Liu Changpeng

2017-04-01 15:22, Yuanhan Liu:
> Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
> net specific.
> 
> Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> ---
>  doc/guides/rel_notes/deprecation.rst   |   9 -
>  doc/guides/rel_notes/release_17_05.rst |   3 +
>  drivers/net/vhost/rte_eth_vhost.c      |   2 +-
>  drivers/net/vhost/rte_eth_vhost.h      |   2 +-
>  examples/tep_termination/main.c        |   2 +-
>  examples/tep_termination/vxlan_setup.c |   2 +-
>  examples/vhost/main.c                  |   2 +-
>  lib/librte_vhost/Makefile              |   2 +-
>  lib/librte_vhost/rte_vhost.h           | 425 +++++++++++++++++++++++++++++++++
>  lib/librte_vhost/rte_virtio_net.h      | 425 ---------------------------------
>  lib/librte_vhost/vhost.c               |   2 +-
>  lib/librte_vhost/vhost.h               |   2 +-
>  lib/librte_vhost/vhost_user.h          |   2 +-
>  lib/librte_vhost/virtio_net.c          |   2 +-
>  14 files changed, 438 insertions(+), 444 deletions(-)
>  create mode 100644 lib/librte_vhost/rte_vhost.h
>  delete mode 100644 lib/librte_vhost/rte_virtio_net.h

It must be renamed also in doc/api/doxy-api-index.md:
-  [vhost]              (@ref rte_virtio_net.h),
+  [vhost]              (@ref rte_vhost.h),

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

* Re: [PATCH v4 19/22] vhost: rename header file
  2017-04-05  0:26         ` Thomas Monjalon
@ 2017-04-05  5:16           ` Yuanhan Liu
  0 siblings, 0 replies; 135+ messages in thread
From: Yuanhan Liu @ 2017-04-05  5:16 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev, Maxime Coquelin, Harris James R, Liu Changpeng

On Wed, Apr 05, 2017 at 02:26:20AM +0200, Thomas Monjalon wrote:
> 2017-04-01 15:22, Yuanhan Liu:
> > Rename "rte_virtio_net.h" to "rte_vhost.h", to not let it be virtio
> > net specific.
> > 
> > Signed-off-by: Yuanhan Liu <yuanhan.liu@linux.intel.com>
> > Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
> > ---
> >  doc/guides/rel_notes/deprecation.rst   |   9 -
> >  doc/guides/rel_notes/release_17_05.rst |   3 +
> >  drivers/net/vhost/rte_eth_vhost.c      |   2 +-
> >  drivers/net/vhost/rte_eth_vhost.h      |   2 +-
> >  examples/tep_termination/main.c        |   2 +-
> >  examples/tep_termination/vxlan_setup.c |   2 +-
> >  examples/vhost/main.c                  |   2 +-
> >  lib/librte_vhost/Makefile              |   2 +-
> >  lib/librte_vhost/rte_vhost.h           | 425 +++++++++++++++++++++++++++++++++
> >  lib/librte_vhost/rte_virtio_net.h      | 425 ---------------------------------
> >  lib/librte_vhost/vhost.c               |   2 +-
> >  lib/librte_vhost/vhost.h               |   2 +-
> >  lib/librte_vhost/vhost_user.h          |   2 +-
> >  lib/librte_vhost/virtio_net.c          |   2 +-
> >  14 files changed, 438 insertions(+), 444 deletions(-)
> >  create mode 100644 lib/librte_vhost/rte_vhost.h
> >  delete mode 100644 lib/librte_vhost/rte_virtio_net.h
> 
> It must be renamed also in doc/api/doxy-api-index.md:
> -  [vhost]              (@ref rte_virtio_net.h),
> +  [vhost]              (@ref rte_vhost.h),

Oops, wasn't aware of that. I saw you have already handled that while
applying. Thanks for that!

	--yliu

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

end of thread, other threads:[~2017-04-05  5:19 UTC | newest]

Thread overview: 135+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-03  9:51 [PATCH 00/17] vhost: generic vhost API Yuanhan Liu
2017-03-03  9:51 ` [PATCH 01/17] vhost: introduce driver features related APIs Yuanhan Liu
2017-03-14  9:46   ` Maxime Coquelin
2017-03-14  9:53     ` Maxime Coquelin
2017-03-16  7:08       ` Yuanhan Liu
2017-03-16  9:18         ` Maxime Coquelin
2017-03-17  5:50           ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 02/17] net/vhost: remove feature " Yuanhan Liu
2017-03-14 10:15   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 03/17] vhost: use new APIs to handle features Yuanhan Liu
2017-03-14 10:43   ` Maxime Coquelin
2017-03-16  7:43     ` Yuanhan Liu
2017-03-16  9:39       ` Maxime Coquelin
2017-03-17  5:48         ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 04/17] vhost: make notify ops per vhost driver Yuanhan Liu
2017-03-14 10:55   ` Maxime Coquelin
2017-03-16  7:50     ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 05/17] vhost: export guest memory regions Yuanhan Liu
2017-03-14 11:00   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 06/17] vhost: introduce API to fetch negotiated features Yuanhan Liu
2017-03-14 11:02   ` Maxime Coquelin
2017-03-16  7:35     ` Yuanhan Liu
2017-03-16  9:22       ` Maxime Coquelin
2017-03-17  5:49         ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 07/17] vhost: export vhost vring info Yuanhan Liu
2017-03-14 12:11   ` Maxime Coquelin
2017-03-16  7:24     ` Yuanhan Liu
2017-03-16  9:20       ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 08/17] vhost: export API to translate gpa to vva Yuanhan Liu
2017-03-14 12:24   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 09/17] vhost: turn queue pair to vring Yuanhan Liu
2017-03-14 12:31   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 10/17] vhost: export the number of vrings Yuanhan Liu
2017-03-14 12:33   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 11/17] vhost: move the device ready check at proper place Yuanhan Liu
2017-03-14 12:37   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 12/17] vhost: drop the Rx and Tx queue macro Yuanhan Liu
2017-03-14 12:42   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 13/17] vhost: do not include net specific headers Yuanhan Liu
2017-03-14 12:46   ` Maxime Coquelin
2017-03-20  7:32   ` Liu, Changpeng
2017-03-22  6:21     ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 14/17] vhost: rename device ops struct Yuanhan Liu
2017-03-14 12:48   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 15/17] vhost: rename virtio-net to vhost Yuanhan Liu
2017-03-14 12:50   ` Maxime Coquelin
2017-03-03  9:51 ` [PATCH 16/17] vhost: rename header file Yuanhan Liu
2017-03-14 12:59   ` Maxime Coquelin
2017-03-20  5:35     ` Yuanhan Liu
2017-03-03  9:51 ` [PATCH 17/17] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-03-23  7:10 ` [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 02/22] net/vhost: remove feature " Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 03/22] vhost: use new APIs to handle features Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 05/22] vhost: export guest memory regions Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 07/22] vhost: export vhost vring info Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 09/22] vhost: turn queue pair to vring Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 10/22] vhost: export the number of vrings Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 11/22] vhost: move the device ready check at proper place Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 13/22] vhost: do not include net specific headers Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 14/22] vhost: rename device ops struct Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 16/22] vhost: add features changed callback Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 17/22] vhost: export APIs for live migration support Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 19/22] vhost: rename header file Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
2017-03-23  7:10   ` [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-03-28 12:45   ` [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 02/22] net/vhost: remove feature " Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 03/22] vhost: use new APIs to handle features Yuanhan Liu
2017-03-29 14:57       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
2017-03-29 15:03       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 05/22] vhost: export guest memory regions Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
2017-03-31  7:45       ` Maxime Coquelin
2017-03-31  8:51         ` Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 07/22] vhost: export vhost vring info Yuanhan Liu
2017-03-31  7:48       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 09/22] vhost: turn queue pair to vring Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 10/22] vhost: export the number of vrings Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 11/22] vhost: move the device ready check at proper place Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 13/22] vhost: do not include net specific headers Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 14/22] vhost: rename device ops struct Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 16/22] vhost: add features changed callback Yuanhan Liu
2017-03-31  7:50       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 17/22] vhost: export APIs for live migration support Yuanhan Liu
2017-03-31  8:05       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
2017-03-31  9:11       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 19/22] vhost: rename header file Yuanhan Liu
2017-03-28 12:45     ` [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
2017-03-31  9:13       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
2017-03-31  9:26       ` Maxime Coquelin
2017-03-28 12:45     ` [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-04-01  7:22     ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-04-05  0:01         ` Thomas Monjalon
2017-04-01  7:22       ` [PATCH v4 02/22] net/vhost: remove feature " Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 03/22] vhost: use new APIs to handle features Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 04/22] vhost: make notify ops per vhost driver Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 05/22] vhost: export guest memory regions Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 06/22] vhost: introduce API to fetch negotiated features Yuanhan Liu
2017-04-01  8:28         ` Maxime Coquelin
2017-04-01  7:22       ` [PATCH v4 07/22] vhost: export vhost vring info Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 08/22] vhost: export API to translate gpa to vva Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 09/22] vhost: turn queue pair to vring Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 10/22] vhost: export the number of vrings Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 11/22] vhost: move the device ready check at proper place Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro Yuanhan Liu
2017-04-05  0:17         ` Thomas Monjalon
2017-04-01  7:22       ` [PATCH v4 13/22] vhost: do not include net specific headers Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 14/22] vhost: rename device ops struct Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 16/22] vhost: add features changed callback Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 17/22] vhost: export APIs for live migration support Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 18/22] vhost: introduce API to start a specific driver Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 19/22] vhost: rename header file Yuanhan Liu
2017-04-05  0:26         ` Thomas Monjalon
2017-04-05  5:16           ` Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 20/22] vhost: workaround the build dependency on mbuf header Yuanhan Liu
2017-04-01  7:22       ` [PATCH v4 21/22] vhost: do not destroy device on repeat mem table message Yuanhan Liu
2017-04-01  7:23       ` [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-04-01  8:44       ` [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu

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.