{
const struct rte_flow_item_gtp *gtp_spec;
const struct rte_flow_item_gtp *gtp_mask;
- const struct rte_flow_item_gtp_psc *spec;
const struct rte_flow_item_gtp_psc *mask;
const struct rte_flow_item_gtp_psc nic_mask = {
- .pdu_type = 0xFF,
- .qfi = 0xFF,
+ .hdr.type = 0xF,
+ .hdr.qfi = 0x3F,
};
if (!gtp_item || !(last_item & MLX5_FLOW_LAYER_GTP))
/* GTP spec is here and E flag is requested to match zero. */
if (!item->spec)
return 0;
- spec = item->spec;
mask = item->mask ? item->mask : &rte_flow_item_gtp_psc_mask;
- if (spec->pdu_type > MLX5_GTP_EXT_MAX_PDU_TYPE)
- return rte_flow_error_set
- (error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, item,
- "PDU type should be smaller than 16");
return mlx5_flow_item_acceptable(item, (const uint8_t *)mask,
(const uint8_t *)&nic_mask,
sizeof(struct rte_flow_item_gtp_psc),
MLX5_SET(fte_match_set_misc, misc_v, geneve_opt_len,
geneve_opt_v->option_len + 1);
}
+ MLX5_SET(fte_match_set_misc, misc_m, geneve_tlv_option_0_exist, 1);
+ MLX5_SET(fte_match_set_misc, misc_v, geneve_tlv_option_0_exist, 1);
/* Set the data. */
if (geneve_opt_v->data) {
memcpy(&opt_data_key, geneve_opt_v->data,
if (!gtp_psc_m)
gtp_psc_m = &rte_flow_item_gtp_psc_mask;
dw_0.w32 = 0;
- dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_m->pdu_type);
- dw_0.qfi = gtp_psc_m->qfi;
+ dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_m->hdr.type);
+ dw_0.qfi = gtp_psc_m->hdr.qfi;
MLX5_SET(fte_match_set_misc3, misc3_m, gtpu_first_ext_dw_0,
rte_cpu_to_be_32(dw_0.w32));
dw_0.w32 = 0;
- dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->pdu_type &
- gtp_psc_m->pdu_type);
- dw_0.qfi = gtp_psc_v->qfi & gtp_psc_m->qfi;
+ dw_0.type_flags = MLX5_GTP_PDU_TYPE_SHIFT(gtp_psc_v->hdr.type &
+ gtp_psc_m->hdr.type);
+ dw_0.qfi = gtp_psc_v->hdr.qfi & gtp_psc_m->hdr.qfi;
MLX5_SET(fte_match_set_misc3, misc3_v, gtpu_first_ext_dw_0,
rte_cpu_to_be_32(dw_0.w32));
}
* Flow matcher value.
* @param[in] item
* Flow pattern to translate.
- * @param[in] samples
- * Sample IDs to be used in the matching.
+ * @param[in] last_item
+ * Last item flags.
*/
static void
flow_dv_translate_item_ecpri(struct rte_eth_dev *dev, void *matcher,
- void *key, const struct rte_flow_item *item)
+ void *key, const struct rte_flow_item *item,
+ uint64_t last_item)
{
struct mlx5_priv *priv = dev->data->dev_private;
const struct rte_flow_item_ecpri *ecpri_m = item->mask;
void *dw_m;
void *dw_v;
+ /*
+ * In case of eCPRI over Ethernet, if EtherType is not specified,
+ * match on eCPRI EtherType implicitly.
+ */
+ if (last_item & MLX5_FLOW_LAYER_OUTER_L2) {
+ void *hdrs_m, *hdrs_v, *l2m, *l2v;
+
+ hdrs_m = MLX5_ADDR_OF(fte_match_param, matcher, outer_headers);
+ hdrs_v = MLX5_ADDR_OF(fte_match_param, key, outer_headers);
+ l2m = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_m, ethertype);
+ l2v = MLX5_ADDR_OF(fte_match_set_lyr_2_4, hdrs_v, ethertype);
+ if (*(uint16_t *)l2m == 0 && *(uint16_t *)l2v == 0) {
+ *(uint16_t *)l2m = UINT16_MAX;
+ *(uint16_t *)l2v = RTE_BE16(RTE_ETHER_TYPE_ECPRI);
+ }
+ }
if (!ecpri_v)
return;
if (!ecpri_m)
}
static inline int
-flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx)
+flow_dv_aso_ct_release(struct rte_eth_dev *dev, uint32_t own_idx,
+ struct rte_flow_error *error)
{
uint16_t owner = (uint16_t)MLX5_INDIRECT_ACT_CT_GET_OWNER(own_idx);
uint32_t idx = MLX5_INDIRECT_ACT_CT_GET_IDX(own_idx);
struct rte_eth_dev *owndev = &rte_eth_devices[owner];
- RTE_SET_USED(dev);
+ int ret;
MLX5_ASSERT(owner < RTE_MAX_ETHPORTS);
if (dev->data->dev_started != 1)
- return -1;
- return flow_dv_aso_ct_dev_release(owndev, idx);
+ return rte_flow_error_set(error, EAGAIN,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Indirect CT action cannot be destroyed when the port is stopped");
+ ret = flow_dv_aso_ct_dev_release(owndev, idx);
+ if (ret < 0)
+ return rte_flow_error_set(error, EAGAIN,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Current state prevents indirect CT action from being destroyed");
+ return ret;
}
/*
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);
+ owner_idx = (uint32_t)(uintptr_t)action->conf;
+ age_act = flow_aso_age_get_by_idx(dev, owner_idx);
+ if (flow->age == 0) {
+ flow->age = owner_idx;
+ __atomic_fetch_add(&age_act->refcnt, 1,
+ __ATOMIC_RELAXED);
+ }
age_act_pos = actions_n++;
action_flags |= MLX5_FLOW_ACTION_AGE;
break;
action_flags |= MLX5_FLOW_ACTION_AGE;
break;
case MLX5_RTE_FLOW_ACTION_TYPE_COUNT:
- cnt_act = flow_dv_counter_get_by_idx(dev,
- (uint32_t)(uintptr_t)action->conf,
- NULL);
+ owner_idx = (uint32_t)(uintptr_t)action->conf;
+ cnt_act = flow_dv_counter_get_by_idx(dev, owner_idx,
+ NULL);
MLX5_ASSERT(cnt_act != NULL);
/**
* When creating meter drop flow in drop table, the
dev_flow->dv.actions[actions_n++] =
cnt_act->action;
} else {
- flow->counter =
- (uint32_t)(uintptr_t)(action->conf);
- __atomic_fetch_add(&cnt_act->shared_info.refcnt,
- 1, __ATOMIC_RELAXED);
+ if (flow->counter == 0) {
+ flow->counter = owner_idx;
+ __atomic_fetch_add
+ (&cnt_act->shared_info.refcnt,
+ 1, __ATOMIC_RELAXED);
+ }
/* Save information first, will apply later. */
action_flags |= MLX5_FLOW_ACTION_COUNT;
}
else
dev_flow->dv.actions[actions_n] =
ct->dr_action_rply;
- flow->indirect_type = MLX5_INDIRECT_ACTION_TYPE_CT;
- flow->ct = owner_idx;
- __atomic_fetch_add(&ct->refcnt, 1, __ATOMIC_RELAXED);
+ if (flow->ct == 0) {
+ flow->indirect_type =
+ MLX5_INDIRECT_ACTION_TYPE_CT;
+ flow->ct = owner_idx;
+ __atomic_fetch_add(&ct->refcnt, 1,
+ __ATOMIC_RELAXED);
+ }
actions_n++;
action_flags |= MLX5_FLOW_ACTION_CT;
break;
"cannot create eCPRI parser");
}
flow_dv_translate_item_ecpri(dev, match_mask,
- match_value, items);
+ match_value, items,
+ last_item);
/* No other protocol should follow eCPRI layer. */
last_item = MLX5_FLOW_LAYER_ECPRI;
break;
}
/* Keep the current age handling by default. */
if (flow->indirect_type == MLX5_INDIRECT_ACTION_TYPE_CT && flow->ct)
- flow_dv_aso_ct_release(dev, flow->ct);
+ flow_dv_aso_ct_release(dev, flow->ct, NULL);
else if (flow->age)
flow_dv_aso_age_release(dev, flow->age);
if (flow->geneve_tlv_option) {
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, EBUSY,
- RTE_FLOW_ERROR_TYPE_ACTION,
- NULL,
- "shared rss hrxq has references");
if (!__atomic_compare_exchange_n(&shared_rss->refcnt, &old_refcnt,
0, 0, __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
RTE_FLOW_ERROR_TYPE_ACTION,
NULL,
"shared rss has references");
+ remaining = __flow_dv_action_rss_hrxqs_release(dev, shared_rss);
+ if (remaining)
+ return rte_flow_error_set(error, EBUSY,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "shared rss hrxq has references");
queue = shared_rss->ind_tbl->queues;
remaining = mlx5_ind_table_obj_release(dev, shared_rss->ind_tbl, true);
if (remaining)
" released with references %d.", idx, ret);
return 0;
case MLX5_INDIRECT_ACTION_TYPE_CT:
- ret = flow_dv_aso_ct_release(dev, idx);
+ ret = flow_dv_aso_ct_release(dev, idx, error);
if (ret < 0)
return ret;
if (ret > 0)
policy->act_cnt[i].fate_action == MLX5_FLOW_FATE_MTR)
next_fm = mlx5_flow_meter_find(priv,
policy->act_cnt[i].next_mtr_id, NULL);
- TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
+ RTE_TAILQ_FOREACH_SAFE(color_rule, &sub_policy->color_rules[i],
next_port, tmp) {
claim_zero(mlx5_flow_os_destroy_flow(color_rule->rule));
tbl = container_of(color_rule->matcher->tbl,
RTE_MTR_ERROR_TYPE_POLICER_ACTION_GREEN,
NULL,
"Multiple fate actions not supported.");
+ *hierarchy_domain = 0;
while (true) {
fm = mlx5_flow_meter_find(priv, meter_id, NULL);
if (!fm)
"Non termination meter not supported in hierarchy.");
policy = mlx5_flow_meter_policy_find(dev, fm->policy_id, NULL);
MLX5_ASSERT(policy);
- if (!policy->is_hierarchy) {
+ /**
+ * Only inherit the supported domains of the first meter in
+ * hierarchy.
+ * One meter supports at least one domain.
+ */
+ if (!*hierarchy_domain) {
if (policy->transfer)
*hierarchy_domain |=
MLX5_MTR_DOMAIN_TRANSFER_BIT;
MLX5_MTR_DOMAIN_INGRESS_BIT;
if (policy->egress)
*hierarchy_domain |= MLX5_MTR_DOMAIN_EGRESS_BIT;
+ }
+ if (!policy->is_hierarchy) {
*is_rss = policy->is_rss;
break;
}
* so MARK action is only in ingress domain.
*/
domain_color[i] = MLX5_MTR_DOMAIN_INGRESS_BIT;
- else if (action_flags[i] &
- MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
- domain_color[i] = hierarchy_domain;
else
domain_color[i] = def_domain;
+ if (action_flags[i] &
+ MLX5_FLOW_ACTION_METER_WITH_TERMINATED_POLICY)
+ domain_color[i] &= hierarchy_domain;
/*
* Non-termination actions only support NIC Tx domain.
* The adjustion should be skipped when there is no