vhost: introduce operation to get vDPA queue stats

The vDPA device offloads all the datapath of the vhost
device to the HW device.

In order to expose to the user traffic information this
patch introduces new 3 APIs to get traffic statistics, the
device statistics name and to reset the statistics per
virtio queue.

The statistics are taken directly from the vDPA driver
managing the HW device and can be different for each vendor
driver.

Signed-off-by: Matan Azrad <matan@mellanox.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
This commit is contained in:
Matan Azrad 2020-06-18 18:59:41 +00:00 committed by Ferruh Yigit
parent d1c074bd76
commit 1cb4415751
6 changed files with 173 additions and 1 deletions

View File

@ -68,6 +68,11 @@ New Features
* Added new PMD devarg ``reclaim_mem_mode``.
* **Added vDPA device APIs to query virtio queue statistics.**
A new 3 APIs has been added to query virtio queue statistics, to get their
names and to reset them by a vDPA device.
* **Added support for BPF_ABS/BPF_IND load instructions.**
Added support for two BPF non-generic instructions:

View File

@ -37,6 +37,7 @@ proto rarp =
proto reply ack =
proto host notifier =
proto pagefault =
queue statistics =
BSD nic_uio =
Linux VFIO =
Other kdrv =

View File

@ -96,6 +96,9 @@ proto host notifier
proto pagefault
Slave expose page-fault FD for migration process.
queue statistics
Support virtio queue statistics query.
BSD nic_uio
BSD ``nic_uio`` module supported.

View File

@ -37,6 +37,34 @@ struct rte_vdpa_dev_addr {
};
};
/** Maximum name length for statistics counters */
#define RTE_VDPA_STATS_NAME_SIZE 64
/**
* A vDPA device statistic structure
*
* This structure is used by rte_vdpa_stats_get() to provide
* statistics from the HW vDPA device.
*
* It maps a name id, corresponding to an index in the array returned
* by rte_vdpa_get_stats_names, to a statistic value.
*/
struct rte_vdpa_stat {
uint64_t id; /**< The index in stats name array */
uint64_t value; /**< The statistic counter value */
};
/**
* A name element for statistics
*
* An array of this structure is returned by rte_vdpa_get_stats_names
* It lists the names of extended statistics for a PMD. The rte_vdpa_stat
* structure references these names by their array index
*/
struct rte_vdpa_stat_name {
char name[RTE_VDPA_STATS_NAME_SIZE]; /**< The statistic name */
};
/**
* vdpa device operations
*/
@ -73,8 +101,19 @@ struct rte_vdpa_dev_ops {
int (*get_notify_area)(int vid, int qid,
uint64_t *offset, uint64_t *size);
/** Get statistics name */
int (*get_stats_names)(int did, struct rte_vdpa_stat_name *stats_names,
unsigned int size);
/** Get statistics of the queue */
int (*get_stats)(int did, int qid, struct rte_vdpa_stat *stats,
unsigned int n);
/** Reset statistics of the queue */
int (*reset_stats)(int did, int qid);
/** Reserved for future extension */
void *reserved[5];
void *reserved[2];
};
/**
@ -200,4 +239,78 @@ rte_vhost_host_notifier_ctrl(int vid, bool enable);
__rte_experimental
int
rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Retrieve names of statistics of a vDPA device.
*
* There is an assumption that 'stat_names' and 'stats' arrays are matched
* by array index: stats_names[i].name => stats[i].value
*
* And the array index is same with id field of 'struct rte_vdpa_stat':
* stats[i].id == i
*
* @param did
* device id
* @param stats_names
* array of at least size elements to be filled.
* If set to NULL, the function returns the required number of elements.
* @param size
* The number of elements in stats_names array.
* @return
* A negative value on error, otherwise the number of entries filled in the
* stats name array.
*/
__rte_experimental
int
rte_vdpa_get_stats_names(int did, struct rte_vdpa_stat_name *stats_names,
unsigned int size);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Retrieve statistics of a vDPA device.
*
* There is an assumption that 'stat_names' and 'stats' arrays are matched
* by array index: stats_names[i].name => stats[i].value
*
* And the array index is same with id field of 'struct rte_vdpa_stat':
* stats[i].id == i
*
* @param did
* device id
* @param qid
* queue id
* @param stats
* A pointer to a table of structure of type rte_vdpa_stat to be filled with
* device statistics ids and values.
* @param n
* The number of elements in stats array.
* @return
* A negative value on error, otherwise the number of entries filled in the
* stats table.
*/
__rte_experimental
int
rte_vdpa_get_stats(int did, uint16_t qid, struct rte_vdpa_stat *stats,
unsigned int n);
/**
* @warning
* @b EXPERIMENTAL: this API may change without prior notice
*
* Reset statistics of a vDPA device.
*
* @param did
* device id
* @param qid
* queue id
* @return
* 0 on success, a negative value on error.
*/
__rte_experimental
int
rte_vdpa_reset_stats(int did, uint16_t qid);
#endif /* _RTE_VDPA_H_ */

View File

@ -38,6 +38,9 @@ EXPERIMENTAL {
rte_vdpa_find_device_id;
rte_vdpa_get_device;
rte_vdpa_get_device_num;
rte_vdpa_get_stats_names;
rte_vdpa_get_stats;
rte_vdpa_reset_stats;
rte_vhost_driver_attach_vdpa_device;
rte_vhost_driver_detach_vdpa_device;
rte_vhost_driver_get_vdpa_device_id;

View File

@ -227,3 +227,50 @@ rte_vdpa_relay_vring_used(int vid, uint16_t qid, void *vring_m)
free_ind_table(idesc);
return -1;
}
int
rte_vdpa_get_stats_names(int did, struct rte_vdpa_stat_name *stats_names,
unsigned int size)
{
struct rte_vdpa_device *vdpa_dev;
vdpa_dev = rte_vdpa_get_device(did);
if (!vdpa_dev)
return -ENODEV;
RTE_FUNC_PTR_OR_ERR_RET(vdpa_dev->ops->get_stats_names, -ENOTSUP);
return vdpa_dev->ops->get_stats_names(did, stats_names, size);
}
int
rte_vdpa_get_stats(int did, uint16_t qid, struct rte_vdpa_stat *stats,
unsigned int n)
{
struct rte_vdpa_device *vdpa_dev;
vdpa_dev = rte_vdpa_get_device(did);
if (!vdpa_dev)
return -ENODEV;
if (!stats || !n)
return -EINVAL;
RTE_FUNC_PTR_OR_ERR_RET(vdpa_dev->ops->get_stats, -ENOTSUP);
return vdpa_dev->ops->get_stats(did, qid, stats, n);
}
int
rte_vdpa_reset_stats(int did, uint16_t qid)
{
struct rte_vdpa_device *vdpa_dev;
vdpa_dev = rte_vdpa_get_device(did);
if (!vdpa_dev)
return -ENODEV;
RTE_FUNC_PTR_OR_ERR_RET(vdpa_dev->ops->reset_stats, -ENOTSUP);
return vdpa_dev->ops->reset_stats(did, qid);
}