From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D7F8FA058A; Sun, 22 Mar 2020 13:00:25 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 2DFFF2E8F; Sun, 22 Mar 2020 13:00:25 +0100 (CET) Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 1D80B3B5 for ; Sun, 22 Mar 2020 13:00:22 +0100 (CET) IronPort-SDR: YawR5ZN25grf5sc6rQGyT95crrHiC7he3QYF+LjO/1FNMbgdmesr1ciSg42p185jvAQF1xvenO v2LlBzg4H00w== X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Mar 2020 05:00:21 -0700 IronPort-SDR: FncpxnyyuNPDAraMeAo0bp88lQhYbA0E7DHkQFLbc7HoUi6u4YSodKOxxLstBJlFoO4fAdtS04 cLRbv6YWXfJA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.72,292,1580803200"; d="scan'208";a="419211339" Received: from yexl-server.sh.intel.com (HELO localhost) ([10.67.117.17]) by orsmga005.jf.intel.com with ESMTP; 22 Mar 2020 05:00:19 -0700 Date: Sun, 22 Mar 2020 19:57:17 +0800 From: Ye Xiaolong To: Sivaprasad Tummala Cc: Maxime Coquelin , Zhihong Wang , John McNamara , Marko Kovacevic , dev@dpdk.org Message-ID: <20200322115717.GA2334@intel.com> References: <20200311052401.12063-1-Sivaprasad.Tummala@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20200311052401.12063-1-Sivaprasad.Tummala@intel.com> User-Agent: Mutt/1.9.4 (2018-02-28) Subject: Re: [dpdk-dev] [DPDK v1] examples/vhost: add vhostpmd support X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Hi, Tummala A few comments inline. On 03/11, Sivaprasad Tummala wrote: >Added vHostPMD based configuration of vHost devices. >Currently vHost library calls are used for configuring the >vhost device. > >vHostPMD is a pre-requisite for enabling future features >supported such as FPGA and possibly CBDMA. With the >vHostPMD integration, upstream features in PMD can be easily >supported and additional features such as queue stats for >vhost devices can be useful. > >With the patch, user has an option to select >vHost PMD by passing "--use-vhost-pmd" option. >Disabled by default. > >Note: vHost multi-queue is not enabled on this patch. > >Signed-off-by: Sivaprasad Tummala >--- > doc/guides/sample_app_ug/vhost.rst | 4 + > examples/vhost/Makefile | 4 + > examples/vhost/main.c | 475 ++++++++++++++++++++++++----- > examples/vhost/main.h | 1 + > examples/vhost/meson.build | 3 +- > 5 files changed, 402 insertions(+), 85 deletions(-) > >diff --git a/doc/guides/sample_app_ug/vhost.rst b/doc/guides/sample_app_ug/vhost.rst >index a71ada654..bb6275249 100644 >--- a/doc/guides/sample_app_ug/vhost.rst >+++ b/doc/guides/sample_app_ug/vhost.rst >@@ -152,6 +152,10 @@ note that if NIC is bound to driver with iommu enabled, dequeue zero copy > cannot work at VM2NIC mode (vm2vm=0) due to currently we don't setup iommu > dma mapping for guest memory. > >+**--use-vhost-pmd** >+vHost DPDK PMD will be enabled when this option is given. By default, vHost >+direct library calls are used to configure devices. >+ > **--vlan-strip 0|1** > VLAN strip option is removed, because different NICs have different behaviors > when disabling VLAN strip. Such feature, which heavily depends on hardware, >diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile >index f2b161541..727cbe9d3 100644 >--- a/examples/vhost/Makefile >+++ b/examples/vhost/Makefile >@@ -63,6 +63,10 @@ CFLAGS += -DALLOW_EXPERIMENTAL_API > CFLAGS += -O2 -D_FILE_OFFSET_BITS=64 > CFLAGS += $(WERROR_FLAGS) > >+ifeq ($(CONFIG_RTE_LIBRTE_PMD_VHOST),y) >+LDLIBS += -lrte_pmd_vhost >+endif >+ > include $(RTE_SDK)/mk/rte.extapp.mk > > endif >diff --git a/examples/vhost/main.c b/examples/vhost/main.c >index ab649bf14..b3e331045 100644 >--- a/examples/vhost/main.c >+++ b/examples/vhost/main.c >@@ -24,6 +24,9 @@ > #include > #include > #include >+#ifdef RTE_LIBRTE_PMD_VHOST >+#include >+#endif > > #include "main.h" > >@@ -96,6 +99,9 @@ static int dequeue_zero_copy; > > static int builtin_net_driver; > >+/* Use vHost PMD instead of vHost library (Default) */ >+static int vhost_pmd; >+ > /* 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. */ >@@ -182,6 +188,12 @@ struct mbuf_table lcore_tx_queue[RTE_MAX_LCORE]; > / US_PER_S * BURST_TX_DRAIN_US) > #define VLAN_HLEN 4 > >+static int >+vhost_device_event_callback(uint16_t port_id, >+ enum rte_eth_event_type type, >+ void *param __rte_unused, >+ void *ret_param __rte_unused); >+ > /* > * Builds up the correct configuration for VMDQ VLAN pool map > * according to the pool & queue limits. >@@ -211,6 +223,151 @@ get_eth_conf(struct rte_eth_conf *eth_conf, uint32_t num_devices) > return 0; > } > >+/* >+ * Device removal before application exit >+ * for the device to be re-used >+ */ >+static void >+unregister_device(int socket_num) I think it's the updated version of previous unregister_drivers, why change its name to unregister_device? >+{ >+ int ret; >+ >+ if (vhost_pmd) { >+ char drv_name[RTE_ETH_NAME_MAX_LEN]; >+ struct vhost_dev *vdev = NULL; >+ uint16_t port_id; >+ >+ snprintf(drv_name, RTE_ETH_NAME_MAX_LEN, >+ "net_vhost%d", socket_num); >+ ret = rte_eth_dev_get_port_by_name(drv_name, &port_id); >+ if (ret != 0) >+ rte_exit(EXIT_FAILURE, >+ "vhost device port id get failed.\n"); main func would call rte_exit after unregister_driver, so we could just call RTE_LOG here as the non-vhost-pmd case. >+ >+ TAILQ_FOREACH(vdev, &vhost_dev_list, global_vdev_entry) { >+ if (vdev->eth_dev_id == port_id) { >+ vdev->remove = 1; >+ break; >+ } >+ } >+ >+ /* Close the Ethernet device */ >+ rte_eth_dev_close(port_id); >+ } else { >+ ret = rte_vhost_driver_unregister(socket_files + >+ socket_num * PATH_MAX); >+ if (ret != 0) >+ RTE_LOG(ERR, VHOST_CONFIG, >+ "Fail to unregister vhost driver for %s.\n", >+ socket_files + socket_num * PATH_MAX); >+ } >+} >+ >+/* >+ * Initialises a given port using global settings and with the rx buffers >+ * coming from the mbuf_pool passed as parameter >+ */ >+static inline int >+port_init_v2(uint16_t portid) What about naming it vhost_pmd_port_init to be more descriptive? >+{ >+ struct rte_eth_rxconf rxq_conf; >+ struct rte_eth_txconf txq_conf; >+ struct rte_eth_dev_info dev_info; >+ struct rte_eth_conf port_conf = { >+ .rxmode = { >+ .split_hdr_size = 0, >+ }, >+ .txmode = { >+ .mq_mode = ETH_MQ_TX_NONE, >+ }, >+ }; >+ uint16_t nb_rxd, nb_txd; >+ int ret = 0; >+ >+ /* init port */ >+ printf("Initializing port %u... ", portid); >+ fflush(stdout); >+ >+ ret = rte_eth_dev_info_get(portid, &dev_info); >+ if (ret != 0) >+ rte_exit(EXIT_FAILURE, >+ "Error during getting device (port %u) info: %s\n", >+ portid, strerror(-ret)); main would check the return value of port_init and call ret_exit for failure case, we can just call RTE_LOG here. >+ >+ if (strncmp(dev_info.driver_name, "net_vhost", >+ sizeof("net_vhost")) == 0) >+ rte_eth_dev_callback_register(portid, >+ RTE_ETH_EVENT_INTR_LSC, >+ vhost_device_event_callback, NULL); >+ >+ ret = rte_eth_dev_configure(portid, 1, 1, &port_conf); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", >+ ret, portid); >+ >+ nb_rxd = RTE_TEST_RX_DESC_DEFAULT; >+ nb_txd = RTE_TEST_TX_DESC_DEFAULT; >+ >+ ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, >+ &nb_txd); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, >+ "Cannot adjust number of descriptors: err=%d, port=%u\n", >+ ret, portid); >+ >+ ret = rte_eth_macaddr_get(portid, >+ &vmdq_ports_eth_addr[portid]); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, >+ "Cannot get MAC address: err=%d, port=%u\n", >+ ret, portid); >+ >+ /* init RX queue */ >+ fflush(stdout); >+ rxq_conf = dev_info.default_rxconf; >+ rxq_conf.offloads = port_conf.rxmode.offloads; >+ ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, >+ rte_eth_dev_socket_id(portid), >+ &rxq_conf, >+ mbuf_pool); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", >+ ret, portid); >+ >+ /* init TX queue */ >+ fflush(stdout); >+ txq_conf = dev_info.default_txconf; >+ txq_conf.offloads = port_conf.txmode.offloads; >+ ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, >+ rte_eth_dev_socket_id(portid), >+ &txq_conf); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", >+ ret, portid); >+ >+ /* Start device */ >+ ret = rte_eth_dev_start(portid); >+ if (ret < 0) >+ rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", >+ ret, portid); >+ >+ if (promiscuous) { >+ ret = rte_eth_promiscuous_enable(portid); >+ if ((ret != 0) && (ret != -ENOTSUP)) { >+ uint8_t i; >+ >+ for (i = 0; i < nb_sockets; i++) >+ unregister_device(i); >+ >+ rte_exit(EXIT_FAILURE, >+ "rte_eth_promiscuous_enable:err=%s, port=%u\n", >+ rte_strerror(-ret), portid); >+ } >+ } >+ >+ return 0; >+} >+ > /* > * Initialises a given port using global settings and with the rx buffers > * coming from the mbuf_pool passed as parameter >@@ -461,7 +618,8 @@ us_vhost_usage(const char *prgname) > " --tx-csum [0|1] disable/enable TX checksum offload.\n" > " --tso [0|1] disable/enable TCP segment offload.\n" > " --client register a vhost-user socket as client mode.\n" >- " --dequeue-zero-copy enables dequeue zero copy\n", >+ " --dequeue-zero-copy enables dequeue zero copy.\n" >+ " --use-vhost-pmd enables vHost PMD instead of vHost library\n", > prgname); > } > >@@ -488,6 +646,7 @@ us_vhost_parse_args(int argc, char **argv) > {"client", no_argument, &client_mode, 1}, > {"dequeue-zero-copy", no_argument, &dequeue_zero_copy, 1}, > {"builtin-net-driver", no_argument, &builtin_net_driver, 1}, >+ {"use-vhost-pmd", no_argument, &vhost_pmd, 1}, > {NULL, 0, 0, 0}, > }; > >@@ -1047,37 +1206,61 @@ drain_eth_rx(struct vhost_dev *vdev) > if (!rx_count) > return; > >- /* >- * When "enable_retry" is set, here we wait and retry when there >- * is no enough free slots in the queue to hold @rx_count packets, >- * to diminish packet loss. >- */ >- if (enable_retry && >- unlikely(rx_count > rte_vhost_avail_entries(vdev->vid, >- VIRTIO_RXQ))) { >- uint32_t retry; >- >- for (retry = 0; retry < burst_rx_retry_num; retry++) { >- rte_delay_us(burst_rx_delay_time); >- if (rx_count <= rte_vhost_avail_entries(vdev->vid, >- VIRTIO_RXQ)) >- break; >+ if (vhost_pmd) { >+ enqueue_count = rte_eth_tx_burst(vdev->eth_dev_id, 0, >+ pkts, rx_count); >+ if (unlikely(enqueue_count < rx_count)) { >+ uint32_t retry, pending = rx_count - enqueue_count; >+ for (retry = 0; retry < burst_rx_retry_num; retry++) { >+ rte_delay_us(burst_rx_delay_time); >+ enqueue_count += rte_eth_tx_burst( >+ vdev->eth_dev_id, 0, >+ (pkts + enqueue_count), pending); >+ pending = rx_count - enqueue_count; >+ >+ if (enqueue_count == rx_count) >+ break; >+ } >+ /* Drop the remaining packets */ >+ uint32_t idx; This mixed declaration and code statement. >+ for (idx = enqueue_count; idx < rx_count; idx++) >+ rte_pktmbuf_free(pkts[idx]); > } >- } >- >- 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); >+ /* >+ * When "enable_retry" is set, here we wait and retry >+ * when there is no enough free slots in the queue to >+ * hold @rx_count packets, to diminish packet loss. >+ */ >+ if (enable_retry && >+ unlikely(rx_count > rte_vhost_avail_entries( >+ vdev->vid, VIRTIO_RXQ))) { >+ uint32_t retry; >+ >+ for (retry = 0; retry < >+ burst_rx_retry_num; retry++) { >+ rte_delay_us(burst_rx_delay_time); >+ if (rx_count <= rte_vhost_avail_entries( >+ vdev->vid, VIRTIO_RXQ)) >+ break; >+ } >+ } >+ >+ 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); >+ } >+ >+ free_pkts(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); > } >- >- free_pkts(pkts, rx_count); > } > > static __rte_always_inline void >@@ -1087,12 +1270,20 @@ drain_virtio_tx(struct vhost_dev *vdev) > uint16_t count; > uint16_t i; > >- if (builtin_net_driver) { >- count = vs_dequeue_pkts(vdev, VIRTIO_TXQ, mbuf_pool, >- pkts, MAX_PKT_BURST); >+ if (vhost_pmd) { >+ count = rte_eth_rx_burst(vdev->eth_dev_id, >+ 0, pkts, MAX_PKT_BURST); >+ if (!count) >+ return; >+ > } else { >- count = rte_vhost_dequeue_burst(vdev->vid, VIRTIO_TXQ, >- mbuf_pool, pkts, MAX_PKT_BURST); >+ 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 */ >@@ -1291,6 +1482,91 @@ static const struct vhost_device_ops virtio_net_device_ops = > .destroy_device = destroy_device, > }; > >+static int >+vhost_device_attach_callback(uint16_t port_id) >+{ >+ int lcore, core_add = 0, vid = -1; >+ uint32_t device_num_min = num_devices; >+ struct vhost_dev *vdev; >+ >+#ifdef RTE_LIBRTE_PMD_VHOST >+ vid = rte_eth_vhost_get_vid_from_port_id(port_id); >+#endif >+ >+ vdev = rte_zmalloc("vhost device", sizeof(*vdev), RTE_CACHE_LINE_SIZE); >+ if (vdev == NULL) { >+ RTE_LOG(INFO, VHOST_DATA, >+ "(%d) couldn't allocate memory for vhost dev\n", >+ vid); >+ return -1; >+ } >+ >+ 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; >+ >+ /*reset ready flag*/ >+ vdev->ready = DEVICE_MAC_LEARNING; >+ vdev->remove = 0; >+ >+ vdev->vid = vid; >+ vdev->eth_dev_id = port_id; >+ >+ /* Find a suitable lcore to add the device. */ >+ RTE_LCORE_FOREACH_SLAVE(lcore) { >+ if (lcore_info[lcore].device_num < device_num_min) { >+ device_num_min = lcore_info[lcore].device_num; >+ core_add = lcore; >+ } >+ } >+ vdev->coreid = core_add; >+ >+ TAILQ_INSERT_TAIL(&lcore_info[vdev->coreid].vdev_list, vdev, >+ lcore_vdev_entry); >+ lcore_info[vdev->coreid].device_num++; >+ >+ return 0; >+} >+ >+int >+vhost_device_event_callback(uint16_t port_id, >+ enum rte_eth_event_type type, >+ void *param __rte_unused, >+ void *ret_param __rte_unused) >+{ >+ struct rte_eth_link link; >+ int vid = -1; >+ >+ if (type == RTE_ETH_EVENT_INTR_LSC) { >+ rte_eth_link_get_nowait(port_id, &link); >+ >+ if (link.link_status) { >+ RTE_LOG(INFO, VHOST_DATA, >+ "Port %d Link Up - speed %u Mbps - %s\n", >+ port_id, (unsigned int) link.link_speed, >+ (link.link_duplex == ETH_LINK_FULL_DUPLEX) >+ ? "full-duplex" : "half-duplex"); >+ if (vhost_device_attach_callback(port_id) != 0) { >+ RTE_LOG(ERR, VHOST_DATA, >+ "vhost dev (%d) attach callback failed\n", >+ port_id); >+ return -1; >+ } >+ } else { >+ RTE_LOG(INFO, VHOST_DATA, "Port %d Link Down\n", >+ port_id); >+#ifdef RTE_LIBRTE_PMD_VHOST >+ vid = rte_eth_vhost_get_vid_from_port_id(port_id); >+#endif >+ destroy_device(vid); >+ } >+ } >+ >+ return 0; >+} >+ > /* > * This is a thread will wake up after a period to print stats if the user has > * enabled them. >@@ -1339,26 +1615,15 @@ print_stats(__rte_unused void *arg) > return NULL; > } > >-static void >-unregister_drivers(int socket_num) >-{ >- int i, ret; >- >- for (i = 0; i < socket_num; i++) { >- ret = rte_vhost_driver_unregister(socket_files + i * PATH_MAX); >- if (ret != 0) >- RTE_LOG(ERR, VHOST_CONFIG, >- "Fail to unregister vhost driver for %s.\n", >- socket_files + i * PATH_MAX); >- } >-} >- > /* When we receive a INT signal, unregister vhost driver */ > static void > sigint_handler(__rte_unused int signum) > { > /* Unregister vhost driver. */ >- unregister_drivers(nb_sockets); >+ uint8_t i; >+ >+ for (i = 0; i < nb_sockets; i++) >+ unregister_device(i); > > exit(0); > } >@@ -1441,6 +1706,14 @@ main(int argc, char *argv[]) > if (ret < 0) > rte_exit(EXIT_FAILURE, "Invalid argument\n"); > >+#ifndef RTE_LIBRTE_PMD_VHOST >+ if (vhost_pmd == 1) { >+ RTE_LOG(ERR, VHOST_CONFIG, "Use vHost PMD is not supported\n"); >+ rte_exit(EXIT_FAILURE, "vHost PMD should be enabled in" >+ " config file\n"); >+ } >+#endif >+ > for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { > TAILQ_INIT(&lcore_info[lcore_id].vdev_list); > >@@ -1517,52 +1790,86 @@ main(int argc, char *argv[]) > /* Register vhost user driver to handle vhost messages. */ > for (i = 0; i < nb_sockets; i++) { > 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 (builtin_net_driver) >- rte_vhost_driver_set_features(file, VIRTIO_NET_FEATURES); >+ if (vhost_pmd) { >+ char dev_name[PATH_MAX]; >+ char drv_name[RTE_ETH_NAME_MAX_LEN]; >+ uint16_t port; >+ >+ snprintf(drv_name, RTE_ETH_NAME_MAX_LEN, >+ "net_vhost%d", i); >+ snprintf(dev_name, PATH_MAX, "%s," >+ "iface=%s,client=%d,tso=%d," >+ "dequeue-zero-copy=%d", >+ drv_name, file, client_mode, >+ enable_tso, dequeue_zero_copy); >+ >+ ret = rte_dev_probe(dev_name); I am wondering whether we can use vhost-pmd by specifying net_vhost vdev in eal options. >+ if (ret != 0) { >+ rte_exit(EXIT_FAILURE, >+ "vhost user device probe failed\n"); >+ } >+ ret = rte_eth_dev_get_port_by_name(drv_name, &port); >+ if (ret != 0) { >+ unregister_device(i); Here unregister_device only deals with one registered vhost driver, but we need to get rid of all registered ones before rte_exit, right? And same for below 2 unregister. >+ rte_exit(EXIT_FAILURE, >+ "vhost device port id get failed.\n"); >+ } >+ ret = port_init_v2(port); >+ if (ret != 0) { >+ unregister_device(i); >+ rte_exit(EXIT_FAILURE, >+ "vhost device port initialization failed.\n"); >+ } >+ } else { >+ ret = rte_vhost_driver_register(file, flags); >+ if (ret != 0) { >+ unregister_device(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 (builtin_net_driver) >+ rte_vhost_driver_set_features(file, >+ VIRTIO_NET_FEATURES); > >- if (enable_tx_csum == 0) { >- rte_vhost_driver_disable_features(file, >- 1ULL << VIRTIO_NET_F_CSUM); >- } >+ if (mergeable == 0) { >+ rte_vhost_driver_disable_features(file, >+ 1ULL << VIRTIO_NET_F_MRG_RXBUF); >+ } > >- 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 (enable_tx_csum == 0) { >+ rte_vhost_driver_disable_features(file, >+ 1ULL << VIRTIO_NET_F_CSUM); >+ } > >- if (promiscuous) { >- rte_vhost_driver_enable_features(file, >- 1ULL << VIRTIO_NET_F_CTRL_RX); >- } >+ 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); >+ } > >- 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"); >- } >+ if (promiscuous) { >+ rte_vhost_driver_enable_features(file, >+ 1ULL << VIRTIO_NET_F_CTRL_RX); >+ } > >- if (rte_vhost_driver_start(file) < 0) { >- rte_exit(EXIT_FAILURE, >- "failed to start vhost driver.\n"); >+ 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"); >+ } >+ >+ if (rte_vhost_driver_start(file) < 0) { >+ rte_exit(EXIT_FAILURE, >+ "failed to start vhost driver.\n"); >+ } > } > } > >diff --git a/examples/vhost/main.h b/examples/vhost/main.h >index 7cba0edbf..023f43891 100644 >--- a/examples/vhost/main.h >+++ b/examples/vhost/main.h >@@ -48,6 +48,7 @@ struct vhost_dev { > volatile uint8_t remove; > > int vid; >+ uint16_t eth_dev_id; > uint64_t features; > size_t hdr_len; > uint16_t nr_vrings; >diff --git a/examples/vhost/meson.build b/examples/vhost/meson.build >index 872d51153..158add5eb 100644 >--- a/examples/vhost/meson.build >+++ b/examples/vhost/meson.build >@@ -9,7 +9,8 @@ > if not is_linux > build = false > endif >-deps += 'vhost' >+build = dpdk_conf.has('RTE_LIBRTE_PMD_VHOST') >+deps += 'pmd_vhost' > allow_experimental_apis = true > sources = files( > 'main.c', 'virtio_net.c' >-- >2.17.1 >