diff --git a/Documentation/topics/dpdk/vhost-user.rst b/Documentation/topics/dpdk/vhost-user.rst index 368f44520..724aa62f6 100644 --- a/Documentation/topics/dpdk/vhost-user.rst +++ b/Documentation/topics/dpdk/vhost-user.rst @@ -350,6 +350,31 @@ The default value is ``false``. .. _dpdk-testpmd: +vhost-user-client tx retries config +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For vhost-user-client interfaces, the max amount of retries can be changed from +the default 8 by setting ``tx-retries-max``. + +The minimum is 0 which means there will be no retries and if any packets in +each batch cannot be sent immediately they will be dropped. The maximum is 32, +which would mean that after the first packet(s) in the batch was sent there +could be a maximum of 32 more retries. + +Retries can help with avoiding packet loss when temporarily unable to send to a +vhost interface because the virtqueue is full. However, spending more time +retrying to send to one interface, will reduce the time available for rx/tx and +processing packets on other interfaces, so some tuning may be required for best +performance. + +Tx retries max can be set for vhost-user-client ports:: + + $ ovs-vsctl set Interface vhost-client-1 options:tx-retries-max=0 + +.. note:: + + Configurable vhost tx retries are not supported with vhost-user ports. + DPDK in the Guest ----------------- @@ -495,6 +520,9 @@ there will be a retry, with a default maximum of 8 occurring. If at any time no packets can be sent, it may mean the guest is not accepting packets, so there are no (more) retries. +For information about configuring the maximum amount of tx retries for +vhost-user-client interfaces see `vhost-user-client tx retries config`_. + .. note:: Maximum vhost tx batch size is defined by NETDEV_MAX_BURST, and is currently diff --git a/NEWS b/NEWS index 6db1af8b1..81130e667 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,8 @@ Post-v2.11.0 * OVS validated with DPDK 18.11.2 which is the new minimal supported version. * DPDK 18.11.1 and lower is no longer supported. + * New option 'tx-retries-max' to set the maximum amount of vhost tx + retries that can be made. - OpenFlow: * All features required by OpenFlow 1.5 are now implemented, so ovs-vswitchd now enables OpenFlow 1.5 by default (in addition to diff --git a/lib/netdev-dpdk.c b/lib/netdev-dpdk.c index 51a885270..48057835f 100644 --- a/lib/netdev-dpdk.c +++ b/lib/netdev-dpdk.c @@ -164,7 +164,13 @@ BUILD_ASSERT_DECL((MAX_NB_MBUF / ROUND_DOWN_POW2(MAX_NB_MBUF / MIN_NB_MBUF)) typedef uint16_t dpdk_port_t; #define DPDK_PORT_ID_FMT "%"PRIu16 -#define VHOST_ENQ_RETRY_NUM 8 +/* Minimum amount of vhost tx retries, effectively a disable. */ +#define VHOST_ENQ_RETRY_MIN 0 +/* Maximum amount of vhost tx retries. */ +#define VHOST_ENQ_RETRY_MAX 32 +/* Legacy default value for vhost tx retries. */ +#define VHOST_ENQ_RETRY_DEF 8 + #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ) static const struct rte_eth_conf port_conf = { @@ -417,7 +423,9 @@ struct netdev_dpdk { /* True if vHost device is 'up' and has been reconfigured at least once */ bool vhost_reconfigured; - /* 3 pad bytes here. */ + + atomic_uint8_t vhost_tx_retries_max; + /* 2 pad bytes here. */ ); PADDED_MEMBERS(CACHE_LINE_SIZE, @@ -1261,6 +1269,8 @@ vhost_common_construct(struct netdev *netdev) return ENOMEM; } + atomic_init(&dev->vhost_tx_retries_max, VHOST_ENQ_RETRY_DEF); + return common_construct(netdev, DPDK_ETH_PORT_ID_INVALID, DPDK_DEV_VHOST, socket_id); } @@ -1921,6 +1931,7 @@ netdev_dpdk_vhost_client_set_config(struct netdev *netdev, { struct netdev_dpdk *dev = netdev_dpdk_cast(netdev); const char *path; + int max_tx_retries, cur_max_tx_retries; ovs_mutex_lock(&dev->mutex); if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) { @@ -1937,6 +1948,19 @@ netdev_dpdk_vhost_client_set_config(struct netdev *netdev, netdev_request_reconfigure(netdev); } } + + max_tx_retries = smap_get_int(args, "tx-retries-max", + VHOST_ENQ_RETRY_DEF); + if (max_tx_retries < VHOST_ENQ_RETRY_MIN + || max_tx_retries > VHOST_ENQ_RETRY_MAX) { + max_tx_retries = VHOST_ENQ_RETRY_DEF; + } + atomic_read_relaxed(&dev->vhost_tx_retries_max, &cur_max_tx_retries); + if (max_tx_retries != cur_max_tx_retries) { + atomic_store_relaxed(&dev->vhost_tx_retries_max, max_tx_retries); + VLOG_INFO("Max Tx retries for vhost device '%s' set to %d", + netdev_get_name(netdev), max_tx_retries); + } ovs_mutex_unlock(&dev->mutex); return 0; @@ -2350,6 +2374,7 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid, unsigned int total_pkts = cnt; unsigned int dropped = 0; int i, retries = 0; + int max_retries = VHOST_ENQ_RETRY_MIN; int vid = netdev_dpdk_get_vid(dev); qid = dev->tx_q[qid % netdev->n_txq].map; @@ -2379,18 +2404,25 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid, cnt -= tx_pkts; /* Prepare for possible retry.*/ cur_pkts = &cur_pkts[tx_pkts]; + if (OVS_UNLIKELY(cnt && !retries)) { + /* + * Read max retries as there are packets not sent + * and no retries have already occurred. + */ + atomic_read_relaxed(&dev->vhost_tx_retries_max, &max_retries); + } } else { /* No packets sent - do not retry.*/ break; } - } while (cnt && (retries++ < VHOST_ENQ_RETRY_NUM)); + } while (cnt && (retries++ < max_retries)); rte_spinlock_unlock(&dev->tx_q[qid].tx_lock); rte_spinlock_lock(&dev->stats_lock); netdev_dpdk_vhost_update_tx_counters(&dev->stats, pkts, total_pkts, cnt + dropped); - dev->tx_retries += MIN(retries, VHOST_ENQ_RETRY_NUM); + dev->tx_retries += MIN(retries, max_retries); rte_spinlock_unlock(&dev->stats_lock); out: diff --git a/vswitchd/vswitch.xml b/vswitchd/vswitch.xml index dc31b282d..6d99f7c27 100644 --- a/vswitchd/vswitch.xml +++ b/vswitchd/vswitch.xml @@ -3127,6 +3127,18 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
++ The value specifies the maximum amount of vhost tx retries that can + be made while trying to send a batch of packets to an interface. + Only supported by dpdkvhostuserclient interfaces. +
++ Default value is 8. +
+