ethdev: keep count of representor ranges in API
In its current state, the API can overflow the user-passed buffer if a new
representor range appears between function calls.
In order to solve this problem, augment the representor info structure with
the numbers of allocated and initialized ranges. This way the users of this
structure can be sure they will not overrun the buffer.
Fixes: 85e1588ca7
("ethdev: add API to get representor info")
Cc: stable@dpdk.org
Signed-off-by: Viacheslav Galaktionov <viacheslav.galaktionov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Xueming Li <xuemingl@nvidia.com>
This commit is contained in:
parent
7bc7bc3516
commit
10eaf41d70
@ -413,9 +413,15 @@ mlx5_representor_info_get(struct rte_eth_dev *dev,
|
|||||||
int n_type = 4; /* Representor types, VF, HPF@VF, SF and HPF@SF. */
|
int n_type = 4; /* Representor types, VF, HPF@VF, SF and HPF@SF. */
|
||||||
int n_pf = 2; /* Number of PFs. */
|
int n_pf = 2; /* Number of PFs. */
|
||||||
int i = 0, pf;
|
int i = 0, pf;
|
||||||
|
int n_entries;
|
||||||
|
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
n_entries = n_type * n_pf;
|
||||||
|
if ((uint32_t)n_entries > info->nb_ranges_alloc)
|
||||||
|
n_entries = info->nb_ranges_alloc;
|
||||||
|
|
||||||
info->controller = 0;
|
info->controller = 0;
|
||||||
info->pf = priv->pf_bond >= 0 ? priv->pf_bond : 0;
|
info->pf = priv->pf_bond >= 0 ? priv->pf_bond : 0;
|
||||||
for (pf = 0; pf < n_pf; ++pf) {
|
for (pf = 0; pf < n_pf; ++pf) {
|
||||||
@ -431,6 +437,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev,
|
|||||||
snprintf(info->ranges[i].name,
|
snprintf(info->ranges[i].name,
|
||||||
sizeof(info->ranges[i].name), "pf%dvf", pf);
|
sizeof(info->ranges[i].name), "pf%dvf", pf);
|
||||||
i++;
|
i++;
|
||||||
|
if (i == n_entries)
|
||||||
|
break;
|
||||||
/* HPF range of VF type. */
|
/* HPF range of VF type. */
|
||||||
info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
|
info->ranges[i].type = RTE_ETH_REPRESENTOR_VF;
|
||||||
info->ranges[i].controller = 0;
|
info->ranges[i].controller = 0;
|
||||||
@ -443,6 +451,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev,
|
|||||||
snprintf(info->ranges[i].name,
|
snprintf(info->ranges[i].name,
|
||||||
sizeof(info->ranges[i].name), "pf%dvf", pf);
|
sizeof(info->ranges[i].name), "pf%dvf", pf);
|
||||||
i++;
|
i++;
|
||||||
|
if (i == n_entries)
|
||||||
|
break;
|
||||||
/* SF range. */
|
/* SF range. */
|
||||||
info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
|
info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
|
||||||
info->ranges[i].controller = 0;
|
info->ranges[i].controller = 0;
|
||||||
@ -455,6 +465,8 @@ mlx5_representor_info_get(struct rte_eth_dev *dev,
|
|||||||
snprintf(info->ranges[i].name,
|
snprintf(info->ranges[i].name,
|
||||||
sizeof(info->ranges[i].name), "pf%dsf", pf);
|
sizeof(info->ranges[i].name), "pf%dsf", pf);
|
||||||
i++;
|
i++;
|
||||||
|
if (i == n_entries)
|
||||||
|
break;
|
||||||
/* HPF range of SF type. */
|
/* HPF range of SF type. */
|
||||||
info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
|
info->ranges[i].type = RTE_ETH_REPRESENTOR_SF;
|
||||||
info->ranges[i].controller = 0;
|
info->ranges[i].controller = 0;
|
||||||
@ -467,7 +479,10 @@ mlx5_representor_info_get(struct rte_eth_dev *dev,
|
|||||||
snprintf(info->ranges[i].name,
|
snprintf(info->ranges[i].name,
|
||||||
sizeof(info->ranges[i].name), "pf%dsf", pf);
|
sizeof(info->ranges[i].name), "pf%dsf", pf);
|
||||||
i++;
|
i++;
|
||||||
|
if (i == n_entries)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
info->nb_ranges = i;
|
||||||
out:
|
out:
|
||||||
return n_type * n_pf;
|
return n_type * n_pf;
|
||||||
}
|
}
|
||||||
|
@ -6002,7 +6002,8 @@ rte_eth_representor_id_get(const struct rte_eth_dev *ethdev,
|
|||||||
int controller, int pf, int representor_port,
|
int controller, int pf, int representor_port,
|
||||||
uint16_t *repr_id)
|
uint16_t *repr_id)
|
||||||
{
|
{
|
||||||
int ret, n, i, count;
|
int ret, n, count;
|
||||||
|
uint32_t i;
|
||||||
struct rte_eth_representor_info *info = NULL;
|
struct rte_eth_representor_info *info = NULL;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
@ -6026,6 +6027,7 @@ rte_eth_representor_id_get(const struct rte_eth_dev *ethdev,
|
|||||||
info = calloc(1, size);
|
info = calloc(1, size);
|
||||||
if (info == NULL)
|
if (info == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
info->nb_ranges_alloc = n;
|
||||||
ret = rte_eth_representor_info_get(ethdev->data->port_id, info);
|
ret = rte_eth_representor_info_get(ethdev->data->port_id, info);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
@ -6038,7 +6040,7 @@ rte_eth_representor_id_get(const struct rte_eth_dev *ethdev,
|
|||||||
|
|
||||||
/* Locate representor ID. */
|
/* Locate representor ID. */
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
for (i = 0; i < n; ++i) {
|
for (i = 0; i < info->nb_ranges; ++i) {
|
||||||
if (info->ranges[i].type != type)
|
if (info->ranges[i].type != type)
|
||||||
continue;
|
continue;
|
||||||
if (info->ranges[i].controller != controller)
|
if (info->ranges[i].controller != controller)
|
||||||
|
@ -4856,6 +4856,8 @@ struct rte_eth_representor_range {
|
|||||||
struct rte_eth_representor_info {
|
struct rte_eth_representor_info {
|
||||||
uint16_t controller; /**< Controller ID of caller device. */
|
uint16_t controller; /**< Controller ID of caller device. */
|
||||||
uint16_t pf; /**< Physical function ID of caller device. */
|
uint16_t pf; /**< Physical function ID of caller device. */
|
||||||
|
uint32_t nb_ranges_alloc; /**< Size of the ranges array. */
|
||||||
|
uint32_t nb_ranges; /**< Number of initialized ranges. */
|
||||||
struct rte_eth_representor_range ranges[];/**< Representor ID range. */
|
struct rte_eth_representor_range ranges[];/**< Representor ID range. */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4871,11 +4873,16 @@ struct rte_eth_representor_info {
|
|||||||
* A pointer to a representor info structure.
|
* A pointer to a representor info structure.
|
||||||
* NULL to return number of range entries and allocate memory
|
* NULL to return number of range entries and allocate memory
|
||||||
* for next call to store detail.
|
* for next call to store detail.
|
||||||
|
* The number of ranges that were written into this structure
|
||||||
|
* will be placed into its nb_ranges field. This number cannot be
|
||||||
|
* larger than the nb_ranges_alloc that by the user before calling
|
||||||
|
* this function. It can be smaller than the value returned by the
|
||||||
|
* function, however.
|
||||||
* @return
|
* @return
|
||||||
* - (-ENOTSUP) if operation is not supported.
|
* - (-ENOTSUP) if operation is not supported.
|
||||||
* - (-ENODEV) if *port_id* invalid.
|
* - (-ENODEV) if *port_id* invalid.
|
||||||
* - (-EIO) if device is removed.
|
* - (-EIO) if device is removed.
|
||||||
* - (>=0) number of representor range entries supported by device.
|
* - (>=0) number of available representor range entries.
|
||||||
*/
|
*/
|
||||||
__rte_experimental
|
__rte_experimental
|
||||||
int rte_eth_representor_info_get(uint16_t port_id,
|
int rte_eth_representor_info_get(uint16_t port_id,
|
||||||
|
Loading…
Reference in New Issue
Block a user