return 0;
}
+/**
+ * Append dynamic encap action to the dynamic action list.
+ *
+ * @param[in] priv
+ * Pointer to the port private data structure.
+ * @param[in] acts
+ * Pointer to the template HW steering DR actions.
+ * @param[in] type
+ * Action type.
+ * @param[in] action_src
+ * Offset of source rte flow action.
+ * @param[in] action_dst
+ * Offset of destination DR action.
+ * @param[in] encap_src
+ * Offset of source encap raw data.
+ * @param[in] encap_dst
+ * Offset of destination encap raw data.
+ * @param[in] len
+ * Length of the data to be updated.
+ *
+ * @return
+ * 0 on success, negative value otherwise and rte_errno is set.
+ */
+static __rte_always_inline int
+__flow_hw_act_data_encap_append(struct mlx5_priv *priv,
+ struct mlx5_hw_actions *acts,
+ enum rte_flow_action_type type,
+ uint16_t action_src,
+ uint16_t action_dst,
+ uint16_t encap_src,
+ uint16_t encap_dst,
+ uint16_t len)
+{ struct mlx5_action_construct_data *act_data;
+
+ act_data = __flow_hw_act_data_alloc(priv, type, action_src, action_dst);
+ if (!act_data)
+ return -1;
+ act_data->encap.src = encap_src;
+ act_data->encap.dst = encap_dst;
+ act_data->encap.len = len;
+ LIST_INSERT_HEAD(&acts->act_list, act_data, next);
+ return 0;
+}
+
/**
* Append shared RSS action to the dynamic action list.
*
return 0;
}
+/**
+ * Translate encap items to encapsulation list.
+ *
+ * @param[in] dev
+ * Pointer to the rte_eth_dev data structure.
+ * @param[in] acts
+ * Pointer to the template HW steering DR actions.
+ * @param[in] type
+ * Action type.
+ * @param[in] action_src
+ * Offset of source rte flow action.
+ * @param[in] action_dst
+ * Offset of destination DR action.
+ * @param[in] items
+ * Encap item pattern.
+ * @param[in] items_m
+ * Encap item mask indicates which part are constant and dynamic.
+ *
+ * @return
+ * 0 on success, negative value otherwise and rte_errno is set.
+ */
+static __rte_always_inline int
+flow_hw_encap_item_translate(struct rte_eth_dev *dev,
+ struct mlx5_hw_actions *acts,
+ enum rte_flow_action_type type,
+ uint16_t action_src,
+ uint16_t action_dst,
+ const struct rte_flow_item *items,
+ const struct rte_flow_item *items_m)
+{
+ struct mlx5_priv *priv = dev->data->dev_private;
+ size_t len, total_len = 0;
+ uint32_t i = 0;
+
+ for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++, items_m++, i++) {
+ len = flow_dv_get_item_hdr_len(items->type);
+ if ((!items_m->spec ||
+ memcmp(items_m->spec, items->spec, len)) &&
+ __flow_hw_act_data_encap_append(priv, acts, type,
+ action_src, action_dst, i,
+ total_len, len))
+ return -1;
+ total_len += len;
+ }
+ return 0;
+}
+
/**
* Translate rte_flow actions to DR action.
*
struct rte_flow_action *actions = at->actions;
struct rte_flow_action *action_start = actions;
struct rte_flow_action *masks = at->masks;
+ enum mlx5dr_action_reformat_type refmt_type = 0;
+ const struct rte_flow_action_raw_encap *raw_encap_data;
+ const struct rte_flow_item *enc_item = NULL, *enc_item_m = NULL;
+ uint16_t reformat_pos = MLX5_HW_MAX_ACTS, reformat_src = 0;
+ uint8_t *encap_data = NULL;
+ size_t data_size = 0;
bool actions_end = false;
uint32_t type, i;
int err;
}
i++;
break;
+ case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+ MLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);
+ enc_item = ((const struct rte_flow_action_vxlan_encap *)
+ actions->conf)->definition;
+ enc_item_m =
+ ((const struct rte_flow_action_vxlan_encap *)
+ masks->conf)->definition;
+ reformat_pos = i++;
+ reformat_src = actions - action_start;
+ refmt_type = MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;
+ break;
+ case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+ MLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);
+ enc_item = ((const struct rte_flow_action_nvgre_encap *)
+ actions->conf)->definition;
+ enc_item_m =
+ ((const struct rte_flow_action_nvgre_encap *)
+ actions->conf)->definition;
+ reformat_pos = i++;
+ reformat_src = actions - action_start;
+ refmt_type = MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;
+ break;
+ case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+ case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP:
+ MLX5_ASSERT(reformat_pos == MLX5_HW_MAX_ACTS);
+ reformat_pos = i++;
+ refmt_type = MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+ raw_encap_data =
+ (const struct rte_flow_action_raw_encap *)
+ actions->conf;
+ encap_data = raw_encap_data->data;
+ data_size = raw_encap_data->size;
+ if (reformat_pos != MLX5_HW_MAX_ACTS) {
+ refmt_type = data_size <
+ MLX5_ENCAPSULATION_DECISION_SIZE ?
+ MLX5DR_ACTION_REFORMAT_TYPE_TNL_L3_TO_L2 :
+ MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L3;
+ } else {
+ reformat_pos = i++;
+ refmt_type =
+ MLX5DR_ACTION_REFORMAT_TYPE_L2_TO_TNL_L2;
+ }
+ reformat_src = actions - action_start;
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+ reformat_pos = i++;
+ refmt_type = MLX5DR_ACTION_REFORMAT_TYPE_TNL_L2_TO_L2;
+ break;
case RTE_FLOW_ACTION_TYPE_END:
actions_end = true;
break;
break;
}
}
+ if (reformat_pos != MLX5_HW_MAX_ACTS) {
+ uint8_t buf[MLX5_ENCAP_MAX_LEN];
+
+ if (enc_item) {
+ MLX5_ASSERT(!encap_data);
+ if (flow_dv_convert_encap_data
+ (enc_item, buf, &data_size, error) ||
+ flow_hw_encap_item_translate
+ (dev, acts, (action_start + reformat_src)->type,
+ reformat_src, reformat_pos,
+ enc_item, enc_item_m))
+ goto err;
+ encap_data = buf;
+ } else if (encap_data && __flow_hw_act_data_encap_append
+ (priv, acts,
+ (action_start + reformat_src)->type,
+ reformat_src, reformat_pos, 0, 0, data_size)) {
+ goto err;
+ }
+ acts->encap_decap = mlx5_malloc(MLX5_MEM_ZERO,
+ sizeof(*acts->encap_decap) + data_size,
+ 0, SOCKET_ID_ANY);
+ if (!acts->encap_decap)
+ goto err;
+ if (data_size) {
+ acts->encap_decap->data_size = data_size;
+ memcpy(acts->encap_decap->data, encap_data, data_size);
+ }
+ acts->encap_decap->action = mlx5dr_action_create_reformat
+ (priv->dr_ctx, refmt_type,
+ data_size, encap_data,
+ rte_log2_u32(table_attr->nb_flows),
+ mlx5_hw_act_flag[!!attr->group][type]);
+ if (!acts->encap_decap->action)
+ goto err;
+ acts->rule_acts[reformat_pos].action =
+ acts->encap_decap->action;
+ acts->encap_decap_pos = reformat_pos;
+ }
acts->acts_num = i;
return 0;
err:
struct rte_flow_template_table *table = job->flow->table;
struct mlx5_action_construct_data *act_data;
const struct rte_flow_action *action;
+ const struct rte_flow_action_raw_encap *raw_encap_data;
+ const struct rte_flow_item *enc_item = NULL;
+ uint8_t *buf = job->encap_data;
struct rte_flow_attr attr = {
.ingress = 1,
};
} else {
attr.ingress = 1;
}
+ if (hw_acts->encap_decap && hw_acts->encap_decap->data_size)
+ memcpy(buf, hw_acts->encap_decap->data,
+ hw_acts->encap_decap->data_size);
LIST_FOREACH(act_data, &hw_acts->act_list, next) {
uint32_t jump_group;
uint32_t tag;
&rule_acts[act_data->action_dst]))
return -1;
break;
+ case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+ enc_item = ((const struct rte_flow_action_vxlan_encap *)
+ action->conf)->definition;
+ rte_memcpy((void *)&buf[act_data->encap.dst],
+ enc_item[act_data->encap.src].spec,
+ act_data->encap.len);
+ break;
+ case RTE_FLOW_ACTION_TYPE_NVGRE_ENCAP:
+ enc_item = ((const struct rte_flow_action_nvgre_encap *)
+ action->conf)->definition;
+ rte_memcpy((void *)&buf[act_data->encap.dst],
+ enc_item[act_data->encap.src].spec,
+ act_data->encap.len);
+ break;
+ case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+ raw_encap_data =
+ (const struct rte_flow_action_raw_encap *)
+ action->conf;
+ rte_memcpy((void *)&buf[act_data->encap.dst],
+ raw_encap_data->data, act_data->encap.len);
+ MLX5_ASSERT(raw_encap_data->size ==
+ act_data->encap.len);
+ break;
default:
break;
}
}
+ if (hw_acts->encap_decap) {
+ rule_acts[hw_acts->encap_decap_pos].reformat.offset =
+ job->flow->idx - 1;
+ rule_acts[hw_acts->encap_decap_pos].reformat.data = buf;
+ }
return 0;
}
goto err;
}
mem_size += (sizeof(struct mlx5_hw_q_job *) +
+ sizeof(uint8_t) * MLX5_ENCAP_MAX_LEN +
sizeof(struct mlx5_hw_q_job)) *
queue_attr[0]->size;
}
goto err;
}
for (i = 0; i < nb_queue; i++) {
+ uint8_t *encap = NULL;
+
priv->hw_q[i].job_idx = queue_attr[i]->size;
priv->hw_q[i].size = queue_attr[i]->size;
if (i == 0)
&job[queue_attr[i - 1]->size];
job = (struct mlx5_hw_q_job *)
&priv->hw_q[i].job[queue_attr[i]->size];
- for (j = 0; j < queue_attr[i]->size; j++)
+ encap = (uint8_t *)&job[queue_attr[i]->size];
+ for (j = 0; j < queue_attr[i]->size; j++) {
+ job[j].encap_data = &encap[j * MLX5_ENCAP_MAX_LEN];
priv->hw_q[i].job[j] = &job[j];
+ }
}
dr_ctx_attr.pd = priv->sh->cdev->pd;
dr_ctx_attr.queues = nb_queue;