2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

netdev-dpdk: Enable tx-retries-max config.

vhost tx retries can provide some mitigation against
dropped packets due to a temporarily slow guest/limited queue
size for an interface, but on the other hand when a system
is fully loaded those extra cycles retrying could mean
packets are dropped elsewhere.

Up to now max vhost tx retries have been hardcoded, which meant
no tuning and no way to disable for debugging to see if extra
cycles spent retrying resulted in rx drops on some other
interface.

Add an option to change the max retries, with a value of
0 effectively disabling vhost tx retries.

Signed-off-by: Kevin Traynor <ktraynor@redhat.com>
Acked-by: Eelco Chaudron <echaudro@redhat.com>
Acked-by: Flavio Leitner <fbl@sysclose.org>
Acked-by: Ilya Maximets <i.maximets@samsung.com>
Signed-off-by: Ian Stokes <ian.stokes@intel.com>
This commit is contained in:
Kevin Traynor 2019-07-02 01:32:30 +01:00 committed by Ian Stokes
parent c161357d5d
commit 080f080c3b
4 changed files with 78 additions and 4 deletions

View File

@ -350,6 +350,31 @@ The default value is ``false``.
.. _dpdk-testpmd: .. _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 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 packets can be sent, it may mean the guest is not accepting packets, so there
are no (more) retries. 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:: .. note::
Maximum vhost tx batch size is defined by NETDEV_MAX_BURST, and is currently Maximum vhost tx batch size is defined by NETDEV_MAX_BURST, and is currently

2
NEWS
View File

@ -7,6 +7,8 @@ Post-v2.11.0
* OVS validated with DPDK 18.11.2 which is the new minimal supported * OVS validated with DPDK 18.11.2 which is the new minimal supported
version. version.
* DPDK 18.11.1 and lower is no longer supported. * 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: - OpenFlow:
* All features required by OpenFlow 1.5 are now implemented, so * All features required by OpenFlow 1.5 are now implemented, so
ovs-vswitchd now enables OpenFlow 1.5 by default (in addition to ovs-vswitchd now enables OpenFlow 1.5 by default (in addition to

View File

@ -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; typedef uint16_t dpdk_port_t;
#define DPDK_PORT_ID_FMT "%"PRIu16 #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) #define IF_NAME_SZ (PATH_MAX > IFNAMSIZ ? PATH_MAX : IFNAMSIZ)
static const struct rte_eth_conf port_conf = { 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 */ /* True if vHost device is 'up' and has been reconfigured at least once */
bool vhost_reconfigured; bool vhost_reconfigured;
/* 3 pad bytes here. */
atomic_uint8_t vhost_tx_retries_max;
/* 2 pad bytes here. */
); );
PADDED_MEMBERS(CACHE_LINE_SIZE, PADDED_MEMBERS(CACHE_LINE_SIZE,
@ -1261,6 +1269,8 @@ vhost_common_construct(struct netdev *netdev)
return ENOMEM; return ENOMEM;
} }
atomic_init(&dev->vhost_tx_retries_max, VHOST_ENQ_RETRY_DEF);
return common_construct(netdev, DPDK_ETH_PORT_ID_INVALID, return common_construct(netdev, DPDK_ETH_PORT_ID_INVALID,
DPDK_DEV_VHOST, socket_id); 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); struct netdev_dpdk *dev = netdev_dpdk_cast(netdev);
const char *path; const char *path;
int max_tx_retries, cur_max_tx_retries;
ovs_mutex_lock(&dev->mutex); ovs_mutex_lock(&dev->mutex);
if (!(dev->vhost_driver_flags & RTE_VHOST_USER_CLIENT)) { 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); 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); ovs_mutex_unlock(&dev->mutex);
return 0; return 0;
@ -2350,6 +2374,7 @@ __netdev_dpdk_vhost_send(struct netdev *netdev, int qid,
unsigned int total_pkts = cnt; unsigned int total_pkts = cnt;
unsigned int dropped = 0; unsigned int dropped = 0;
int i, retries = 0; int i, retries = 0;
int max_retries = VHOST_ENQ_RETRY_MIN;
int vid = netdev_dpdk_get_vid(dev); int vid = netdev_dpdk_get_vid(dev);
qid = dev->tx_q[qid % netdev->n_txq].map; 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; cnt -= tx_pkts;
/* Prepare for possible retry.*/ /* Prepare for possible retry.*/
cur_pkts = &cur_pkts[tx_pkts]; 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 { } else {
/* No packets sent - do not retry.*/ /* No packets sent - do not retry.*/
break; break;
} }
} while (cnt && (retries++ < VHOST_ENQ_RETRY_NUM)); } while (cnt && (retries++ < max_retries));
rte_spinlock_unlock(&dev->tx_q[qid].tx_lock); rte_spinlock_unlock(&dev->tx_q[qid].tx_lock);
rte_spinlock_lock(&dev->stats_lock); rte_spinlock_lock(&dev->stats_lock);
netdev_dpdk_vhost_update_tx_counters(&dev->stats, pkts, total_pkts, netdev_dpdk_vhost_update_tx_counters(&dev->stats, pkts, total_pkts,
cnt + dropped); cnt + dropped);
dev->tx_retries += MIN(retries, VHOST_ENQ_RETRY_NUM); dev->tx_retries += MIN(retries, max_retries);
rte_spinlock_unlock(&dev->stats_lock); rte_spinlock_unlock(&dev->stats_lock);
out: out:

View File

@ -3127,6 +3127,18 @@ ovs-vsctl add-port br0 p0 -- set Interface p0 type=patch options:peer=p1 \
</p> </p>
</column> </column>
<column name="options" key="tx-retries-max"
type='{"type": "integer", "minInteger": 0, "maxInteger": 32}'>
<p>
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.
</p>
<p>
Default value is 8.
</p>
</column>
<column name="options" key="n_rxq_desc" <column name="options" key="n_rxq_desc"
type='{"type": "integer", "minInteger": 1, "maxInteger": 4096}'> type='{"type": "integer", "minInteger": 1, "maxInteger": 4096}'>
<p> <p>