* [dpdk-dev] [PATCH v2 01/22] vhost: introduce driver features related APIs
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 02/22] net/vhost: remove feature related APIs
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 03/22] vhost: use new APIs to handle features
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 02/22] net/vhost: remove feature " Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 04/22] vhost: make notify ops per vhost driver
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (2 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 05/22] vhost: export guest memory regions
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (3 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 06/22] vhost: introduce API to fetch negotiated features
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (4 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 05/22] vhost: export guest memory regions Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 07/22] vhost: export vhost vring info
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (5 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 08/22] vhost: export API to translate gpa to vva
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (6 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 09/22] vhost: turn queue pair to vring
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (7 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 10/22] vhost: export the number of vrings
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (8 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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, ð_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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 11/22] vhost: move the device ready check at proper place
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (9 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 12/22] vhost: drop the Rx and Tx queue macro
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (10 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 13/22] vhost: do not include net specific headers
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (11 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 14/22] vhost: rename device ops struct
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (12 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 15/22] vhost: rename virtio-net to vhost
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (13 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 16/22] vhost: add features changed callback
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (14 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 17/22] vhost: export APIs for live migration support
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (15 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 18/22] vhost: introduce API to start a specific driver
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (16 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 19/22] vhost: rename header file
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (17 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 20/22] vhost: workaround the build dependency on mbuf header
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (18 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 19/22] vhost: rename header file Yuanhan Liu
@ 2017-03-23 7:10 ` Yuanhan Liu
2017-03-23 7:10 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 21/22] vhost: do not destroy device on repeat mem table message
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (19 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v2 22/22] examples/vhost: demonstrate the new generic vhost APIs
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (20 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API
2017-03-23 7:10 ` [dpdk-dev] [PATCH v2 00/22] vhost: generic vhost API Yuanhan Liu
` (21 preceding siblings ...)
2017-03-23 7:10 ` [dpdk-dev] [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 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 01/22] vhost: introduce driver features related APIs
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 02/22] net/vhost: remove feature related APIs
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 03/22] vhost: use new APIs to handle features
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 03/22] vhost: use new APIs to handle features
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 04/22] vhost: make notify ops per vhost driver
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (2 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 04/22] vhost: make notify ops per vhost driver
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 05/22] vhost: export guest memory regions
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (3 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 06/22] vhost: introduce API to fetch negotiated features
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (4 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 06/22] vhost: introduce API to fetch negotiated features
2017-03-28 12:45 ` [dpdk-dev] [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: [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 07/22] vhost: export vhost vring info
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (5 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 07/22] vhost: export vhost vring info
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 08/22] vhost: export API to translate gpa to vva
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (6 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 09/22] vhost: turn queue pair to vring
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (7 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 10/22] vhost: export the number of vrings
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (8 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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, ð_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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 11/22] vhost: move the device ready check at proper place
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (9 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 12/22] vhost: drop the Rx and Tx queue macro
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (10 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 13/22] vhost: do not include net specific headers
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (11 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 14/22] vhost: rename device ops struct
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (12 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 15/22] vhost: rename virtio-net to vhost
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (13 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-03-28 12:45 ` Yuanhan Liu
2017-03-28 12:45 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 16/22] vhost: add features changed callback
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (14 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 16/22] vhost: add features changed callback
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 17/22] vhost: export APIs for live migration support
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (15 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 17/22] vhost: export APIs for live migration support
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 18/22] vhost: introduce API to start a specific driver
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (16 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 18/22] vhost: introduce API to start a specific driver
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 19/22] vhost: rename header file
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (17 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (18 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 20/22] vhost: workaround the build dependency on mbuf header
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (19 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v3 21/22] vhost: do not destroy device on repeat mem table message
2017-03-28 12:45 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v3 22/22] examples/vhost: demonstrate the new generic vhost APIs
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (20 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API
2017-03-28 12:45 ` [dpdk-dev] [PATCH v3 00/22] vhost: generic vhost API Yuanhan Liu
` (21 preceding siblings ...)
2017-03-28 12:45 ` [dpdk-dev] [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 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v4 01/22] vhost: introduce driver features related APIs
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 02/22] net/vhost: remove feature related APIs
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 03/22] vhost: use new APIs to handle features
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 01/22] vhost: introduce driver features related APIs Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 02/22] net/vhost: remove feature " Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 04/22] vhost: make notify ops per vhost driver
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (2 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 05/22] vhost: export guest memory regions
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (3 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 06/22] vhost: introduce API to fetch negotiated features
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (4 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 07/22] vhost: export vhost vring info
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (5 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 08/22] vhost: export API to translate gpa to vva
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (6 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 07/22] vhost: export vhost vring info Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 09/22] vhost: turn queue pair to vring
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (7 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 10/22] vhost: export the number of vrings
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (8 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 09/22] vhost: turn queue pair to vring Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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, ð_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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 11/22] vhost: move the device ready check at proper place
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (9 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 10/22] vhost: export the number of vrings Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (10 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v4 12/22] vhost: drop the Rx and Tx queue macro
2017-04-01 7:22 ` [dpdk-dev] [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
* [dpdk-dev] [PATCH v4 13/22] vhost: do not include net specific headers
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (11 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 14/22] vhost: rename device ops struct
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (12 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 15/22] vhost: rename virtio-net to vhost
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (13 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 14/22] vhost: rename device ops struct Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 16/22] vhost: add features changed callback
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (14 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 15/22] vhost: rename virtio-net to vhost Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 17/22] vhost: export APIs for live migration support
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (15 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 16/22] vhost: add features changed callback Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 18/22] vhost: introduce API to start a specific driver
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (16 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 19/22] vhost: rename header file
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (17 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v4 19/22] vhost: rename header file
2017-04-01 7:22 ` [dpdk-dev] [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: [dpdk-dev] [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
* [dpdk-dev] [PATCH v4 20/22] vhost: workaround the build dependency on mbuf header
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (18 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 19/22] vhost: rename header file Yuanhan Liu
@ 2017-04-01 7:22 ` Yuanhan Liu
2017-04-01 7:22 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 21/22] vhost: do not destroy device on repeat mem table message
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (19 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs Yuanhan Liu
2017-04-01 8:44 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* [dpdk-dev] [PATCH v4 22/22] examples/vhost: demonstrate the new generic vhost APIs
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (20 preceding siblings ...)
2017-04-01 7:22 ` [dpdk-dev] [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 ` [dpdk-dev] [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 [flat|nested] 135+ messages in thread
* Re: [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API
2017-04-01 7:22 ` [dpdk-dev] [PATCH v4 00/22] vhost: generic vhost API Yuanhan Liu
` (21 preceding siblings ...)
2017-04-01 7:23 ` [dpdk-dev] [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