X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fmlx5%2Fmlx5_flow_dv.c;h=78c710fef9a18029959626897ecf028c49d341b6;hb=fabf8a37241cc4fe5de13e0593bb1e750c5720ee;hp=be93ba97bc6aa058aea456a4b423b05e1838a9d2;hpb=4a42ac1f1ccda89450c0bbb8ee5816246033b785;p=dpdk.git diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index be93ba97bc..78c710fef9 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -81,6 +81,8 @@ flow_dv_encap_decap_resource_release(struct rte_eth_dev *dev, static int flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev, uint32_t port_id); +static void +flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss); /** * Initialize flow attributes structure according to flow items' types. @@ -5926,6 +5928,15 @@ flow_dv_validate(struct rte_eth_dev *dev, const struct rte_flow_attr *attr, /* Meter action will add one more TAG action. */ rw_act_num += MLX5_ACT_NUM_SET_TAG; break; + case MLX5_RTE_FLOW_ACTION_TYPE_AGE: + if (!attr->group) + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "Shared ASO age action is not supported for group 0"); + action_flags |= MLX5_FLOW_ACTION_AGE; + ++actions_n; + break; case RTE_FLOW_ACTION_TYPE_AGE: ret = flow_dv_validate_action_age(action_flags, actions, dev, @@ -7799,6 +7810,7 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *matcher, struct mlx5_priv *priv = dev->data->dev_private; const struct rte_flow_item_ecpri *ecpri_m = item->mask; const struct rte_flow_item_ecpri *ecpri_v = item->spec; + struct rte_ecpri_common_hdr common; void *misc4_m = MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_4); void *misc4_v = MLX5_ADDR_OF(fte_match_param, key, misc_parameters_4); @@ -7839,7 +7851,8 @@ flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *matcher, * Some wildcard rules only matching type field should be supported. */ if (ecpri_m->hdr.dummy[0]) { - switch (ecpri_v->hdr.common.type) { + common.u32 = rte_be_to_cpu_32(ecpri_v->hdr.common.u32); + switch (common.type) { case RTE_ECPRI_MSG_TYPE_IQ_DATA: case RTE_ECPRI_MSG_TYPE_RTC_CTRL: case RTE_ECPRI_MSG_TYPE_DLY_MSR: @@ -8547,7 +8560,7 @@ flow_dv_hrxq_prepare(struct rte_eth_dev *dev, rss_desc->key_len = MLX5_RSS_HASH_KEY_LEN; rss_desc->hash_fields = dev_flow->hash_fields; rss_desc->tunnel = !!(dh->layers & MLX5_FLOW_LAYER_TUNNEL); - rss_desc->standalone = false; + rss_desc->shared_rss = 0; *hrxq_idx = mlx5_hrxq_get(dev, rss_desc); if (!*hrxq_idx) return NULL; @@ -9240,29 +9253,6 @@ flow_dv_create_action_sample(struct rte_eth_dev *dev, return 0; } -/** - * Get ASO age action by index. - * - * @param[in] dev - * Pointer to the Ethernet device structure. - * @param[in] age_idx - * Index to the ASO age action. - * - * @return - * The specified ASO age action. - */ -static struct mlx5_aso_age_action* -flow_dv_aso_age_get_by_idx(struct rte_eth_dev *dev, uint32_t age_idx) -{ - uint16_t pool_idx = age_idx & UINT16_MAX; - uint16_t offset = (age_idx >> 16) & UINT16_MAX; - struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; - struct mlx5_aso_age_pool *pool = mng->pools[pool_idx]; - - return &pool->actions[offset - 1]; -} - /** * Remove an ASO age action from age actions list. * @@ -9295,18 +9285,35 @@ flow_dv_aso_age_remove_from_age(struct rte_eth_dev *dev, } } -static void +/** + * Release an ASO age action. + * + * @param[in] dev + * Pointer to the Ethernet device structure. + * @param[in] age_idx + * Index of ASO age action to release. + * @param[in] flow + * True if the release operation is during flow destroy operation. + * False if the release operation is during action destroy operation. + * + * @return + * 0 when age action was removed, otherwise the number of references. + */ +static int flow_dv_aso_age_release(struct rte_eth_dev *dev, uint32_t age_idx) { struct mlx5_priv *priv = dev->data->dev_private; struct mlx5_aso_age_mng *mng = priv->sh->aso_age_mng; - struct mlx5_aso_age_action *age = flow_dv_aso_age_get_by_idx(dev, - age_idx); + struct mlx5_aso_age_action *age = flow_aso_age_get_by_idx(dev, age_idx); + uint32_t ret = __atomic_sub_fetch(&age->refcnt, 1, __ATOMIC_RELAXED); - flow_dv_aso_age_remove_from_age(dev, age); - rte_spinlock_lock(&mng->free_sl); - LIST_INSERT_HEAD(&mng->free, age, next); - rte_spinlock_unlock(&mng->free_sl); + if (!ret) { + flow_dv_aso_age_remove_from_age(dev, age); + rte_spinlock_lock(&mng->free_sl); + LIST_INSERT_HEAD(&mng->free, age, next); + rte_spinlock_unlock(&mng->free_sl); + } + return ret; } /** @@ -9450,6 +9457,7 @@ flow_dv_aso_age_alloc(struct rte_eth_dev *dev) return 0; /* 0 is an error.*/ } } + __atomic_store_n(&age_free->refcnt, 1, __ATOMIC_RELAXED); return pool->index | ((age_free->offset + 1) << 16); } @@ -9469,12 +9477,12 @@ flow_dv_translate_create_aso_age(struct rte_eth_dev *dev, const struct rte_flow_action_age *age) { uint32_t age_idx = 0; - struct mlx5_aso_age_action *aso_age = NULL; + struct mlx5_aso_age_action *aso_age; age_idx = flow_dv_aso_age_alloc(dev); if (!age_idx) return 0; - aso_age = flow_dv_aso_age_get_by_idx(dev, age_idx); + aso_age = flow_aso_age_get_by_idx(dev, age_idx); aso_age->age_params.context = age->context; aso_age->age_params.timeout = age->timeout; aso_age->age_params.port_id = dev->data->port_id; @@ -9562,6 +9570,7 @@ flow_dv_translate(struct rte_eth_dev *dev, .external = !!dev_flow->external, .transfer = !!attr->transfer, .fdb_def_rule = !!priv->fdb_def_rule, + .skip_scale = !!dev_flow->skip_scale, }; MLX5_ASSERT(wks); @@ -9638,6 +9647,7 @@ flow_dv_translate(struct rte_eth_dev *dev, const uint8_t *rss_key; const struct rte_flow_action_meter *mtr; struct mlx5_flow_tbl_resource *tbl; + struct mlx5_aso_age_action *age_act; uint32_t port_id = 0; struct mlx5_flow_dv_port_id_action_resource port_id_resource; int action_type = actions->type; @@ -9772,10 +9782,20 @@ flow_dv_translate(struct rte_eth_dev *dev, * when expanding items for RSS. */ action_flags |= MLX5_FLOW_ACTION_RSS; - dev_flow->handle->fate_action = MLX5_FLOW_FATE_QUEUE; + dev_flow->handle->fate_action = rss_desc->shared_rss ? + MLX5_FLOW_FATE_SHARED_RSS : + MLX5_FLOW_FATE_QUEUE; + break; + case MLX5_RTE_FLOW_ACTION_TYPE_AGE: + flow->age = (uint32_t)(uintptr_t)(action->conf); + age_act = flow_aso_age_get_by_idx(dev, flow->age); + __atomic_fetch_add(&age_act->refcnt, 1, + __ATOMIC_RELAXED); + dev_flow->dv.actions[actions_n++] = age_act->dr_action; + action_flags |= MLX5_FLOW_ACTION_AGE; break; case RTE_FLOW_ACTION_TYPE_AGE: - if (priv->sh->flow_hit_aso_en) { + if (priv->sh->flow_hit_aso_en && attr->group) { flow->age = flow_dv_translate_create_aso_age (dev, action->conf); if (!flow->age) @@ -9783,9 +9803,9 @@ flow_dv_translate(struct rte_eth_dev *dev, (error, rte_errno, RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "can't create age action"); + "can't create ASO age action"); dev_flow->dv.actions[actions_n++] = - (flow_dv_aso_age_get_by_idx + (flow_aso_age_get_by_idx (dev, flow->age))->dr_action; action_flags |= MLX5_FLOW_ACTION_AGE; break; @@ -9914,6 +9934,7 @@ flow_dv_translate(struct rte_eth_dev *dev, jump_group = ((const struct rte_flow_action_jump *) action->conf)->group; grp_info.std_tbl_fix = 0; + grp_info.skip_scale = 0; ret = mlx5_flow_group_to_table(dev, tunnel, jump_group, &table, @@ -10557,10 +10578,10 @@ __flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx, * * @param[in] dev * Pointer to the Ethernet device structure. - * @param[in] flow - * Shred RSS action holding hash RX queue objects. * @param[in] dev_flow * Pointer to the sub flow. + * @param[in] rss_desc + * Pointer to the RSS descriptor. * @param[out] hrxq * Pointer to retrieved hash RX queue object. * @@ -10568,29 +10589,23 @@ __flow_dv_action_rss_hrxq_lookup(struct rte_eth_dev *dev, uint32_t idx, * Valid hash RX queue index, otherwise 0 and rte_errno is set. */ static uint32_t -__flow_dv_rss_get_hrxq(struct rte_eth_dev *dev, struct rte_flow *flow, - struct mlx5_flow *dev_flow, - struct mlx5_hrxq **hrxq) +__flow_dv_rss_get_hrxq(struct rte_eth_dev *dev, struct mlx5_flow *dev_flow, + struct mlx5_flow_rss_desc *rss_desc, + struct mlx5_hrxq **hrxq) { struct mlx5_priv *priv = dev->data->dev_private; - struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); uint32_t hrxq_idx; - if (flow->shared_rss) { + if (rss_desc->shared_rss) { hrxq_idx = __flow_dv_action_rss_hrxq_lookup - (dev, flow->shared_rss, dev_flow->hash_fields, + (dev, rss_desc->shared_rss, + dev_flow->hash_fields, !!(dev_flow->handle->layers & MLX5_FLOW_LAYER_TUNNEL)); - if (hrxq_idx) { + if (hrxq_idx) *hrxq = mlx5_ipool_get(priv->sh->ipool[MLX5_IPOOL_HRXQ], hrxq_idx); - __atomic_fetch_add(&(*hrxq)->refcnt, 1, - __ATOMIC_RELAXED); - } } else { - struct mlx5_flow_rss_desc *rss_desc = - &wks->rss_desc[!!wks->flow_nested_idx]; - *hrxq = flow_dv_hrxq_prepare(dev, dev_flow, rss_desc, &hrxq_idx); } @@ -10625,8 +10640,15 @@ flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, int err; int idx; struct mlx5_flow_workspace *wks = mlx5_flow_get_thread_workspace(); + struct mlx5_flow_rss_desc *rss_desc = + &wks->rss_desc[!!wks->flow_nested_idx]; MLX5_ASSERT(wks); + if (rss_desc->shared_rss) { + dh = wks->flows[wks->flow_idx - 1].handle; + MLX5_ASSERT(dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS); + dh->rix_srss = rss_desc->shared_rss; + } for (idx = wks->flow_idx - 1; idx >= wks->flow_nested_idx; idx--) { dev_flow = &wks->flows[idx]; dv = &dev_flow->dv; @@ -10641,11 +10663,12 @@ flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, dv->actions[n++] = priv->drop_queue.hrxq->action; } - } else if (dh->fate_action == MLX5_FLOW_FATE_QUEUE && - !dv_h->rix_sample && !dv_h->rix_dest_array) { + } else if ((dh->fate_action == MLX5_FLOW_FATE_QUEUE && + !dv_h->rix_sample && !dv_h->rix_dest_array) || + (dh->fate_action == MLX5_FLOW_FATE_SHARED_RSS)) { struct mlx5_hrxq *hrxq = NULL; uint32_t hrxq_idx = __flow_dv_rss_get_hrxq - (dev, flow, dev_flow, &hrxq); + (dev, dev_flow, rss_desc, &hrxq); if (!hrxq) { rte_flow_error_set (error, rte_errno, @@ -10653,7 +10676,8 @@ flow_dv_apply(struct rte_eth_dev *dev, struct rte_flow *flow, "cannot get hash queue"); goto error; } - dh->rix_hrxq = hrxq_idx; + if (dh->fate_action == MLX5_FLOW_FATE_QUEUE) + dh->rix_hrxq = hrxq_idx; dv->actions[n++] = hrxq->action; } else if (dh->fate_action == MLX5_FLOW_FATE_DEFAULT_MISS) { if (!priv->sh->default_miss_action) { @@ -10699,6 +10723,8 @@ error: if (dh->vf_vlan.tag && dh->vf_vlan.created) mlx5_vlan_vmwa_release(dev, &dh->vf_vlan); } + if (rss_desc->shared_rss) + wks->flows[wks->flow_idx - 1].handle->rix_srss = 0; rte_errno = err; /* Restore rte_errno. */ return -rte_errno; } @@ -10883,6 +10909,25 @@ flow_dv_port_id_action_resource_release(struct rte_eth_dev *dev, &cache->entry); } +/** + * Release shared RSS action resource. + * + * @param dev + * Pointer to Ethernet device. + * @param srss + * Shared RSS action index. + */ +static void +flow_dv_shared_rss_action_release(struct rte_eth_dev *dev, uint32_t srss) +{ + struct mlx5_priv *priv = dev->data->dev_private; + struct mlx5_shared_action_rss *shared_rss; + + shared_rss = mlx5_ipool_get + (priv->sh->ipool[MLX5_IPOOL_RSS_SHARED_ACTIONS], srss); + __atomic_sub_fetch(&shared_rss->refcnt, 1, __ATOMIC_RELAXED); +} + void flow_dv_push_vlan_remove_cb(struct mlx5_cache_list *list, struct mlx5_cache_entry *entry) @@ -10947,6 +10992,9 @@ flow_dv_fate_resource_release(struct rte_eth_dev *dev, flow_dv_port_id_action_resource_release(dev, handle->rix_port_id_action); break; + case MLX5_FLOW_FATE_SHARED_RSS: + flow_dv_shared_rss_action_release(dev, handle->rix_srss); + break; default: DRV_LOG(DEBUG, "Incorrect fate action:%d", handle->fate_action); break; @@ -11113,13 +11161,6 @@ flow_dv_destroy(struct rte_eth_dev *dev, struct rte_flow *flow) if (!flow) return; flow_dv_remove(dev, flow); - 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; @@ -11224,6 +11265,8 @@ __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev, * * @param[in] dev * Pointer to the Ethernet device structure. + * @param[in] action_idx + * Shared RSS action ipool index. * @param[in, out] action * Partially initialized shared RSS action. * @param[out] error @@ -11235,6 +11278,7 @@ __flow_dv_action_rss_hrxqs_release(struct rte_eth_dev *dev, */ static int __flow_dv_action_rss_setup(struct rte_eth_dev *dev, + uint32_t action_idx, struct mlx5_shared_action_rss *action, struct rte_flow_error *error) { @@ -11246,7 +11290,8 @@ __flow_dv_action_rss_setup(struct rte_eth_dev *dev, rss_desc.key_len = MLX5_RSS_HASH_KEY_LEN; rss_desc.const_q = action->origin.queue; rss_desc.queue_num = action->origin.queue_num; - rss_desc.standalone = true; + /* Set non-zero value to indicate a shared RSS. */ + rss_desc.shared_rss = action_idx; for (i = 0; i < MLX5_RSS_HASH_FIELDS_LEN; i++) { uint32_t hrxq_idx; uint64_t hash_fields = mlx5_rss_hash_fields[i]; @@ -11338,7 +11383,7 @@ __flow_dv_action_rss_create(struct rte_eth_dev *dev, 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_action, error)) + if (__flow_dv_action_rss_setup(dev, idx, shared_action, error)) goto error_rss_init; __atomic_add_fetch(&shared_action->refcnt, 1, __ATOMIC_RELAXED); rte_spinlock_lock(&priv->shared_act_sl); @@ -11441,6 +11486,19 @@ flow_dv_action_create(struct rte_eth_dev *dev, idx = (MLX5_SHARED_ACTION_TYPE_RSS << MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; break; + case RTE_FLOW_ACTION_TYPE_AGE: + ret = flow_dv_translate_create_aso_age(dev, action->conf); + idx = (MLX5_SHARED_ACTION_TYPE_AGE << + MLX5_SHARED_ACTION_TYPE_OFFSET) | ret; + if (ret) { + struct mlx5_aso_age_action *aso_age = + flow_aso_age_get_by_idx(dev, ret); + + if (!aso_age->age_params.context) + aso_age->age_params.context = + (void *)(uintptr_t)idx; + } + break; default: rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "action type not supported"); @@ -11478,17 +11536,23 @@ flow_dv_action_destroy(struct rte_eth_dev *dev, switch (type) { case MLX5_SHARED_ACTION_TYPE_RSS: - ret = __flow_dv_action_rss_release(dev, idx, error); - break; + return __flow_dv_action_rss_release(dev, idx, error); + case MLX5_SHARED_ACTION_TYPE_AGE: + ret = flow_dv_aso_age_release(dev, idx); + if (ret) + /* + * In this case, the last flow has a reference will + * actually release the age action. + */ + DRV_LOG(DEBUG, "Shared age action %" PRIu32 " was" + " released with references %d.", idx, ret); + return 0; default: return rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "action type not supported"); } - if (ret) - return ret; - return 0; } /** @@ -11609,9 +11673,41 @@ flow_dv_action_update(struct rte_eth_dev *dev, return rte_flow_error_set(err, ENOTSUP, RTE_FLOW_ERROR_TYPE_ACTION, NULL, - "action type not supported"); + "action type update not supported"); } } + +static int +flow_dv_action_query(struct rte_eth_dev *dev, + const struct rte_flow_shared_action *action, void *data, + struct rte_flow_error *error) +{ + struct mlx5_age_param *age_param; + struct rte_flow_query_age *resp; + 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_AGE: + age_param = &flow_aso_age_get_by_idx(dev, idx)->age_params; + resp = data; + resp->aged = __atomic_load_n(&age_param->state, + __ATOMIC_RELAXED) == AGE_TMOUT ? + 1 : 0; + resp->sec_since_last_hit_valid = !resp->aged; + if (resp->sec_since_last_hit_valid) + resp->sec_since_last_hit = __atomic_load_n + (&age_param->sec_since_last_hit, __ATOMIC_RELAXED); + return 0; + default: + return rte_flow_error_set(error, ENOTSUP, + RTE_FLOW_ERROR_TYPE_ACTION, + NULL, + "action type query not supported"); + } +} + /** * Query a dv flow rule for its statistics via devx. * @@ -11692,7 +11788,7 @@ flow_dv_query_age(struct rte_eth_dev *dev, struct rte_flow *flow, if (flow->age) { struct mlx5_aso_age_action *act = - flow_dv_aso_age_get_by_idx(dev, flow->age); + flow_aso_age_get_by_idx(dev, flow->age); age_param = &act->age_params; } else if (flow->counter) { @@ -12347,26 +12443,24 @@ flow_get_aged_flows(struct rte_eth_dev *dev, NULL, "empty context"); age_info = GET_PORT_AGE_INFO(priv); rte_spinlock_lock(&age_info->aged_sl); - if (priv->sh->flow_hit_aso_en) - LIST_FOREACH(act, &age_info->aged_aso, next) { - nb_flows++; - if (nb_contexts) { - context[nb_flows - 1] = - act->age_params.context; - if (!(--nb_contexts)) - break; - } + LIST_FOREACH(act, &age_info->aged_aso, next) { + nb_flows++; + if (nb_contexts) { + context[nb_flows - 1] = + act->age_params.context; + if (!(--nb_contexts)) + break; } - else - TAILQ_FOREACH(counter, &age_info->aged_counters, next) { - nb_flows++; - if (nb_contexts) { - age_param = MLX5_CNT_TO_AGE(counter); - context[nb_flows - 1] = age_param->context; - if (!(--nb_contexts)) - break; - } + } + TAILQ_FOREACH(counter, &age_info->aged_counters, next) { + nb_flows++; + if (nb_contexts) { + age_param = MLX5_CNT_TO_AGE(counter); + context[nb_flows - 1] = age_param->context; + if (!(--nb_contexts)) + break; } + } rte_spinlock_unlock(&age_info->aged_sl); MLX5_AGE_SET(age_info, MLX5_AGE_TRIGGER); return nb_flows; @@ -12402,14 +12496,23 @@ static int flow_dv_action_validate(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 mlx5_priv *priv = dev->data->dev_private; + RTE_SET_USED(conf); switch (action->type) { case RTE_FLOW_ACTION_TYPE_RSS: - return mlx5_validate_action_rss(dev, action, error); + return mlx5_validate_action_rss(dev, action, err); + case RTE_FLOW_ACTION_TYPE_AGE: + if (!priv->sh->aso_age_mng) + return rte_flow_error_set(err, ENOTSUP, + RTE_FLOW_ERROR_TYPE_UNSPECIFIED, + NULL, + "shared age action not supported"); + return flow_dv_validate_action_age(0, action, dev, 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"); @@ -12461,6 +12564,7 @@ const struct mlx5_flow_driver_ops mlx5_flow_dv_drv_ops = { .action_create = flow_dv_action_create, .action_destroy = flow_dv_action_destroy, .action_update = flow_dv_action_update, + .action_query = flow_dv_action_query, .sync_domain = flow_dv_sync_domain, };