net/netvsc: allow tuning latency with devargs

Allow overriding default guest to host latency on per device basis
with devargs.

Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
This commit is contained in:
Stephen Hemminger 2018-08-30 15:35:09 -07:00 committed by Ferruh Yigit
parent cf2b90756c
commit a25d39a3eb
3 changed files with 75 additions and 4 deletions

View File

@ -103,3 +103,19 @@ The following prerequisites apply:
* Linux kernel support for UIO on vmbus is done with the uio_hv_generic driver.
Full support of multiple queues requires the 4.17 kernel. It is possible
to use the netvsc PMD with 4.16 kernel but it is limited to a single queue.
Netvsc PMD arguments
--------------------
The user can specify below argument in devargs.
#. ``latency``:
A netvsc device uses a mailbox page to indicate to the host that there
is something in the transmit queue. The host scans this page at a
periodic interval. This parameter allows adjusting the value that
is used by the host. Smaller values improve transmit latency, and larger
values save CPU cycles. This parameter is in microseconds.
If the value is too large or too small it will be
ignored by the host. (Default: 50)

View File

@ -14,7 +14,9 @@
#include <rte_memcpy.h>
#include <rte_string_fns.h>
#include <rte_memzone.h>
#include <rte_devargs.h>
#include <rte_malloc.h>
#include <rte_kvargs.h>
#include <rte_atomic.h>
#include <rte_branch_prediction.h>
#include <rte_ether.h>
@ -130,6 +132,55 @@ eth_dev_vmbus_release(struct rte_eth_dev *eth_dev)
eth_dev->intr_handle = NULL;
}
/* handle "latency=X" from devargs */
static int hn_set_latency(const char *key, const char *value, void *opaque)
{
struct hn_data *hv = opaque;
char *endp = NULL;
unsigned long lat;
errno = 0;
lat = strtoul(value, &endp, 0);
if (*value == '\0' || *endp != '\0') {
PMD_DRV_LOG(ERR, "invalid parameter %s=%s", key, value);
return -EINVAL;
}
PMD_DRV_LOG(DEBUG, "set latency %lu usec", lat);
hv->latency = lat * 1000; /* usec to nsec */
return 0;
}
/* Parse device arguments */
static int hn_parse_args(const struct rte_eth_dev *dev)
{
struct hn_data *hv = dev->data->dev_private;
struct rte_devargs *devargs = dev->device->devargs;
static const char * const valid_keys[] = {
"latency",
NULL
};
struct rte_kvargs *kvlist;
if (!devargs)
return 0;
PMD_INIT_LOG(DEBUG, "device args %s %s",
devargs->name, devargs->args);
kvlist = rte_kvargs_parse(devargs->args, valid_keys);
if (!kvlist) {
PMD_DRV_LOG(NOTICE, "invalid parameters");
return -EINVAL;
}
rte_kvargs_process(kvlist, "latency", hn_set_latency, hv);
rte_kvargs_free(kvlist);
return 0;
}
/* Update link status.
* Note: the DPDK definition of "wait_to_complete"
* means block this call until link is up.
@ -263,8 +314,7 @@ static int hn_subchan_configure(struct hn_data *hv,
return err;
}
rte_vmbus_set_latency(hv->vmbus, new_sc,
HN_CHAN_LATENCY_NS);
rte_vmbus_set_latency(hv->vmbus, new_sc, hv->latency);
retry = 0;
chn_index = rte_vmbus_sub_channel_index(new_sc);
@ -626,14 +676,18 @@ eth_hn_dev_init(struct rte_eth_dev *eth_dev)
hv->rxbuf_res = &vmbus->resource[HV_RECV_BUF_MAP];
hv->chim_res = &vmbus->resource[HV_SEND_BUF_MAP];
hv->port_id = eth_dev->data->port_id;
hv->latency = HN_CHAN_LATENCY_NS;
err = hn_parse_args(eth_dev);
if (err)
return err;
/* Initialize primary channel input for control operations */
err = rte_vmbus_chan_open(vmbus, &hv->channels[0]);
if (err)
return err;
rte_vmbus_set_latency(hv->vmbus, hv->channels[0],
HN_CHAN_LATENCY_NS);
rte_vmbus_set_latency(hv->vmbus, hv->channels[0], hv->latency);
hv->primary = hn_rx_queue_alloc(hv, 0,
eth_dev->device->numa_node);

View File

@ -113,6 +113,7 @@ struct hn_data {
uint32_t chim_szmax; /* Max size per buffer */
uint32_t chim_cnt; /* Max packets per buffer */
uint32_t latency;
uint32_t nvs_ver;
uint32_t ndis_ver;
uint32_t rndis_agg_size;