* action handling should be preformed on *shared* actions list returned
* from this call.
*
+ * @param[in] dev
+ * Pointer to Ethernet device.
* @param[in] actions
* List of actions to translate.
* @param[out] shared
* 0 on success, a negative errno value otherwise and rte_errno is set.
*/
static int
-flow_shared_actions_translate(const struct rte_flow_action actions[],
- struct mlx5_translated_shared_action *shared,
- int *shared_n,
- struct rte_flow_action **translated_actions,
- struct rte_flow_error *error)
+flow_shared_actions_translate(struct rte_eth_dev *dev,
+ const struct rte_flow_action actions[],
+ struct mlx5_translated_shared_action *shared,
+ int *shared_n,
+ struct rte_flow_action **translated_actions,
+ struct rte_flow_error *error)
{
+ struct mlx5_priv *priv = dev->data->dev_private;
struct rte_flow_action *translated = NULL;
size_t actions_size;
int n;
}
memcpy(translated, actions, actions_size);
for (shared_end = shared + copied_n; shared < shared_end; shared++) {
- const struct rte_flow_shared_action *shared_action;
-
- shared_action = shared->action;
- switch (shared_action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
+ struct mlx5_shared_action_rss *shared_rss;
+ uint32_t act_idx = (uint32_t)(uintptr_t)shared->action;
+ uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+ uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET)
+ - 1);
+
+ switch (type) {
+ case MLX5_SHARED_ACTION_TYPE_RSS:
+ shared_rss = mlx5_ipool_get
+ (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
translated[shared->index].type =
RTE_FLOW_ACTION_TYPE_RSS;
translated[shared->index].conf =
- &shared_action->rss.origin;
+ &shared_rss->origin;
break;
default:
mlx5_free(translated);
/**
* Get Shared RSS action from the action list.
*
+ * @param[in] dev
+ * Pointer to Ethernet device.
* @param[in] shared
* Pointer to the list of actions.
* @param[in] shared_n
* Actions list length.
*
* @return
- * Pointer to the MLX5 RSS action if exists, otherwise return NULL.
+ * The MLX5 RSS action ID if exists, otherwise return 0.
*/
-static struct mlx5_shared_action_rss *
-flow_get_shared_rss_action(struct mlx5_translated_shared_action *shared,
+static uint32_t
+flow_get_shared_rss_action(struct rte_eth_dev *dev,
+ struct mlx5_translated_shared_action *shared,
int shared_n)
{
struct mlx5_translated_shared_action *shared_end;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_rss;
- for (shared_end = shared + shared_n; shared < shared_end; shared++) {
- struct rte_flow_shared_action *shared_action;
- shared_action = shared->action;
- switch (shared_action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
- __atomic_add_fetch(&shared_action->refcnt, 1,
+ for (shared_end = shared + shared_n; shared < shared_end; shared++) {
+ uint32_t act_idx = (uint32_t)(uintptr_t)shared->action;
+ uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+ uint32_t idx = act_idx &
+ ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
+ switch (type) {
+ case MLX5_SHARED_ACTION_TYPE_RSS:
+ shared_rss = mlx5_ipool_get
+ (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ idx);
+ __atomic_add_fetch(&shared_rss->refcnt, 1,
__ATOMIC_RELAXED);
- return &shared_action->rss;
+ return idx;
default:
break;
}
}
- return NULL;
-}
-
-struct rte_flow_shared_action *
-mlx5_flow_get_shared_rss(struct rte_flow *flow)
-{
- if (flow->shared_rss)
- return container_of(flow->shared_rss,
- struct rte_flow_shared_action, rss);
- else
- return NULL;
+ return 0;
}
static unsigned int
MLX5_ASSERT(wks);
rss_desc = &wks->rss_desc[fidx];
- ret = flow_shared_actions_translate(original_actions,
+ ret = flow_shared_actions_translate(dev, original_actions,
shared_actions,
&shared_actions_n,
&translated_actions, error);
buf->entries = 1;
buf->entry[0].pattern = (void *)(uintptr_t)items;
}
- flow->shared_rss = flow_get_shared_rss_action(shared_actions,
+ flow->shared_rss = flow_get_shared_rss_action(dev, shared_actions,
shared_actions_n);
/*
* Record the start index when there is a nested call. All sub-flows
int shared_actions_n = MLX5_MAX_SHARED_ACTIONS;
const struct rte_flow_action *actions;
struct rte_flow_action *translated_actions = NULL;
- int ret = flow_shared_actions_translate(original_actions,
+ int ret = flow_shared_actions_translate(dev, original_actions,
shared_actions,
&shared_actions_n,
&translated_actions, error);
flow_get_drv_ops(flow_get_drv_type(dev, &attr));
int ret;
- switch (shared_action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
- if (action->type != RTE_FLOW_ACTION_TYPE_RSS) {
- return rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "update action type invalid");
- }
- ret = flow_drv_action_validate(dev, NULL, action, fops, error);
- if (ret)
- return ret;
- return flow_drv_action_update(dev, shared_action, action->conf,
- fops, error);
- default:
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "action type not supported");
- }
+ ret = flow_drv_action_validate(dev, NULL, action, fops, error);
+ if (ret)
+ return ret;
+ return flow_drv_action_update(dev, shared_action, action->conf, fops,
+ error);
}
/**
struct rte_flow_error *error)
{
(void)dev;
- switch (action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
- __atomic_load(&action->refcnt, (uint32_t *)data,
- __ATOMIC_RELAXED);
- return 0;
- default:
- return rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "action type not supported");
- }
+ (void)action;
+ (void)data;
+ return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "action type query not supported");
}
/**
{
struct rte_flow_error error;
struct mlx5_priv *priv = dev->data->dev_private;
- struct rte_flow_shared_action *action;
+ struct mlx5_shared_action_rss *action;
int ret = 0;
+ uint32_t idx;
- while (!LIST_EMPTY(&priv->shared_actions)) {
- action = LIST_FIRST(&priv->shared_actions);
- ret = mlx5_shared_action_destroy(dev, action, &error);
+ ILIST_FOREACH(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ priv->rss_shared_actions, idx, action, next) {
+ ret |= mlx5_shared_action_destroy(dev,
+ (struct rte_flow_shared_action *)(uintptr_t)idx, &error);
}
return ret;
}
* Look up for hash RX queue by hash fields (see enum ibv_rx_hash_fields)
* and tunnel.
*
- * @param[in] action
- * Shred RSS action holding hash RX queue objects.
+ * @param[in] dev
+ * Pointer to the Ethernet device structure.
+ * @param[in] idx
+ * Shared RSS action ID holding hash RX queue objects.
* @param[in] hash_fields
* Defines combination of packet fields to participate in RX hash.
* @param[in] tunnel
* Valid hash RX queue index, otherwise 0.
*/
static uint32_t
-__flow_dv_action_rss_hrxq_lookup(const struct mlx5_shared_action_rss *action,
+__flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx,
const uint64_t hash_fields,
const int tunnel)
{
- const uint32_t *hrxqs = tunnel ? action->hrxq : action->hrxq_tunnel;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_rss =
+ mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
+ const uint32_t *hrxqs = tunnel ? shared_rss->hrxq :
+ shared_rss->hrxq_tunnel;
switch (hash_fields & ~IBV_RX_HASH_INNER) {
case MLX5_RSS_HASH_IPV4:
* If shared action configured for *flow* suitable hash RX queue will be
* retrieved from attached shared action.
*
+ * @param[in] dev
+ * Pointer to the Ethernet device structure.
* @param[in] flow
* Shred RSS action holding hash RX queue objects.
* @param[in] dev_flow
if (flow->shared_rss) {
hrxq_idx = __flow_dv_action_rss_hrxq_lookup
- (flow->shared_rss, dev_flow->hash_fields,
+ (dev, flow->shared_rss, dev_flow->hash_fields,
!!(dev_flow->handle->layers &
MLX5_FLOW_LAYER_TUNNEL));
if (hrxq_idx) {
static void
flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow)
{
- struct rte_flow_shared_action *shared;
struct mlx5_flow_handle *dev_handle;
struct mlx5_priv *priv = dev->data->dev_private;
if (!flow)
return;
flow_dv_remove(dev, flow);
- shared = mlx5_flow_get_shared_rss(flow);
- if (shared)
- __atomic_sub_fetch(&shared->refcnt, 1, __ATOMIC_RELAXED);
+ if (flow->shared_rss) {
+ struct mlx5_shared_action_rss *shared_rss = mlx5_ipool_get
+ (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ flow->shared_rss);
+
+ __atomic_sub_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED);
+ }
if (flow->counter) {
flow_dv_counter_free(dev, flow->counter);
flow->counter = 0;
* error only.
*
* @return
- * A valid shared action handle in case of success, NULL otherwise and
+ * A valid shared action ID in case of success, 0 otherwise and
* rte_errno is set.
*/
-static struct rte_flow_shared_action *
+static uint32_t
__flow_dv_action_rss_create(struct rte_eth_dev *dev,
const struct rte_flow_shared_action_conf *conf,
const struct rte_flow_action_rss *rss,
struct rte_flow_error *error)
{
- struct rte_flow_shared_action *shared_action = NULL;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_action = NULL;
void *queue = NULL;
- struct mlx5_shared_action_rss *shared_rss;
struct rte_flow_action_rss *origin;
const uint8_t *rss_key;
uint32_t queue_size = rss->queue_num * sizeof(uint16_t);
+ uint32_t idx;
RTE_SET_USED(conf);
queue = mlx5_malloc(0, RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
0, SOCKET_ID_ANY);
- shared_action = mlx5_malloc(MLX5_MEM_ZERO, sizeof(*shared_action), 0,
- SOCKET_ID_ANY);
+ shared_action = mlx5_ipool_zmalloc
+ (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], &idx);
if (!shared_action || !queue) {
rte_flow_error_set(error, ENOMEM,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
"cannot allocate resource memory");
goto error_rss_init;
}
- shared_rss = &shared_action->rss;
- shared_rss->queue = queue;
- origin = &shared_rss->origin;
+ if (idx > (1u << MLX5_SHARED_ACTION_TYPE_OFFSET)) {
+ rte_flow_error_set(error, E2BIG,
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "rss action number out of range");
+ goto error_rss_init;
+ }
+ shared_action->queue = queue;
+ origin = &shared_action->origin;
origin->func = rss->func;
origin->level = rss->level;
/* RSS type 0 indicates default RSS type (ETH_RSS_IP). */
origin->types = !rss->types ? ETH_RSS_IP : rss->types;
/* NULL RSS key indicates default RSS key. */
rss_key = !rss->key ? rss_hash_default_key : rss->key;
- memcpy(shared_rss->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
- origin->key = &shared_rss->key[0];
+ memcpy(shared_action->key, rss_key, MLX5_RSS_HASH_KEY_LEN);
+ origin->key = &shared_action->key[0];
origin->key_len = MLX5_RSS_HASH_KEY_LEN;
- memcpy(shared_rss->queue, rss->queue, queue_size);
- origin->queue = shared_rss->queue;
+ memcpy(shared_action->queue, rss->queue, queue_size);
+ origin->queue = shared_action->queue;
origin->queue_num = rss->queue_num;
- if (__flow_dv_action_rss_setup(dev, shared_rss, error))
+ if (__flow_dv_action_rss_setup(dev, shared_action, error))
goto error_rss_init;
- shared_action->type = MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS;
- return shared_action;
+ __atomic_add_fetch(&shared_action->refcnt, 1, __ATOMIC_RELAXED);
+ rte_spinlock_lock(&priv->shared_act_sl);
+ ILIST_INSERT(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ &priv->rss_shared_actions, idx, shared_action, next);
+ rte_spinlock_unlock(&priv->shared_act_sl);
+ return idx;
error_rss_init:
- mlx5_free(shared_action);
- mlx5_free(queue);
- return NULL;
+ if (shared_action)
+ mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ idx);
+ if (queue)
+ mlx5_free(queue);
+ return 0;
}
/**
*
* @param[in] dev
* Pointer to the Ethernet device structure.
- * @param[in] shared_rss
- * The shared RSS action object to be removed.
+ * @param[in] idx
+ * The shared RSS action object ID to be removed.
* @param[out] error
* Perform verbose error reporting if not NULL. Initialized in case of
* error only.
* 0 on success, otherwise negative errno value.
*/
static int
-__flow_dv_action_rss_release(struct rte_eth_dev *dev,
- struct mlx5_shared_action_rss *shared_rss,
- struct rte_flow_error *error)
+__flow_dv_action_rss_release(struct rte_eth_dev *dev, uint32_t idx,
+ struct rte_flow_error *error)
{
- struct rte_flow_shared_action *shared_action = NULL;
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_rss =
+ mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
uint32_t old_refcnt = 1;
- int remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+ int remaining;
- if (remaining) {
+ if (!shared_rss)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "invalid shared action");
+ remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+ if (remaining)
return rte_flow_error_set(error, ETOOMANYREFS,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"shared rss hrxq has references");
- }
- shared_action = container_of(shared_rss,
- struct rte_flow_shared_action, rss);
- if (!__atomic_compare_exchange_n(&shared_action->refcnt, &old_refcnt,
- 0, 0,
- __ATOMIC_ACQUIRE, __ATOMIC_RELAXED)) {
+ if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
+ 0, 0, __ATOMIC_ACQUIRE,
+ __ATOMIC_RELAXED))
return rte_flow_error_set(error, ETOOMANYREFS,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"shared rss has references");
- }
rte_free(shared_rss->queue);
+ rte_spinlock_lock(&priv->shared_act_sl);
+ ILIST_REMOVE(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ &priv->rss_shared_actions, idx, shared_rss, next);
+ rte_spinlock_unlock(&priv->shared_act_sl);
+ mlx5_ipool_free(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS],
+ idx);
return 0;
}
flow_dv_action_create(struct rte_eth_dev *dev,
const struct rte_flow_shared_action_conf *conf,
const struct rte_flow_action *action,
- struct rte_flow_error *error)
+ struct rte_flow_error *err)
{
- struct rte_flow_shared_action *shared_action = NULL;
- struct mlx5_priv *priv = dev->data->dev_private;
+ uint32_t idx = 0;
+ uint32_t ret = 0;
switch (action->type) {
case RTE_FLOW_ACTION_TYPE_RSS:
- shared_action = __flow_dv_action_rss_create(dev, conf,
- action->conf,
- error);
+ ret = __flow_dv_action_rss_create(dev, conf, action->conf, err);
+ idx = (MLX5_SHARED_ACTION_TYPE_RSS <<
+ MLX5_SHARED_ACTION_TYPE_OFFSET) | ret;
break;
default:
- rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
+ rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION,
NULL, "action type not supported");
break;
}
- if (shared_action) {
- __atomic_add_fetch(&shared_action->refcnt, 1,
- __ATOMIC_RELAXED);
- rte_spinlock_lock(&priv->shared_act_sl);
- LIST_INSERT_HEAD(&priv->shared_actions, shared_action, next);
- rte_spinlock_unlock(&priv->shared_act_sl);
- }
- return shared_action;
+ return ret ? (struct rte_flow_shared_action *)(uintptr_t)idx : NULL;
}
/**
struct rte_flow_shared_action *action,
struct rte_flow_error *error)
{
- struct mlx5_priv *priv = dev->data->dev_private;
+ uint32_t act_idx = (uint32_t)(uintptr_t)action;
+ uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+ uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
int ret;
- switch (action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
- ret = __flow_dv_action_rss_release(dev, &action->rss, error);
+ switch (type) {
+ case MLX5_SHARED_ACTION_TYPE_RSS:
+ ret = __flow_dv_action_rss_release(dev, idx, error);
break;
default:
return rte_flow_error_set(error, ENOTSUP,
}
if (ret)
return ret;
- rte_spinlock_lock(&priv->shared_act_sl);
- LIST_REMOVE(action, next);
- rte_spinlock_unlock(&priv->shared_act_sl);
- rte_free(action);
return 0;
}
*
* @param[in] dev
* Pointer to the Ethernet device structure.
- * @param[in] shared_rss
- * The shared RSS action object to be updated.
+ * @param[in] idx
+ * The shared RSS action object ID to be updated.
* @param[in] action_conf
* RSS action specification used to modify *shared_rss*.
* @param[out] error
* @note: currently only support update of RSS queues.
*/
static int
-__flow_dv_action_rss_update(struct rte_eth_dev *dev,
- struct mlx5_shared_action_rss *shared_rss,
+__flow_dv_action_rss_update(struct rte_eth_dev *dev, uint32_t idx,
const struct rte_flow_action_rss *action_conf,
struct rte_flow_error *error)
{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ struct mlx5_shared_action_rss *shared_rss =
+ mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], idx);
size_t i;
int ret;
void *queue = NULL;
uint32_t rss_key_len;
uint32_t queue_size = action_conf->queue_num * sizeof(uint16_t);
+ if (!shared_rss)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "invalid shared action to update");
queue = mlx5_malloc(MLX5_MEM_ZERO,
RTE_ALIGN_CEIL(queue_size, sizeof(void *)),
0, SOCKET_ID_ANY);
for (tunnel = 0; tunnel < 2; tunnel++) {
hrxq_idx = __flow_dv_action_rss_hrxq_lookup
- (shared_rss, hash_fields, tunnel);
+ (dev, idx, hash_fields, tunnel);
MLX5_ASSERT(hrxq_idx);
ret = mlx5_hrxq_modify
(dev, hrxq_idx,
flow_dv_action_update(struct rte_eth_dev *dev,
struct rte_flow_shared_action *action,
const void *action_conf,
- struct rte_flow_error *error)
+ struct rte_flow_error *err)
{
- switch (action->type) {
- case MLX5_RTE_FLOW_ACTION_TYPE_SHARED_RSS:
- return __flow_dv_action_rss_update(dev, &action->rss,
- action_conf, error);
+ uint32_t act_idx = (uint32_t)(uintptr_t)action;
+ uint32_t type = act_idx >> MLX5_SHARED_ACTION_TYPE_OFFSET;
+ uint32_t idx = act_idx & ((1u << MLX5_SHARED_ACTION_TYPE_OFFSET) - 1);
+
+ switch (type) {
+ case MLX5_SHARED_ACTION_TYPE_RSS:
+ return __flow_dv_action_rss_update(dev, idx, action_conf, err);
default:
- return rte_flow_error_set(error, ENOTSUP,
+ return rte_flow_error_set(err, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"action type not supported");