#include "mlx5.h"
#include "mlx5_prm.h"
+enum modify_reg {
+ REG_A,
+ REG_B,
+ REG_C_0,
+ REG_C_1,
+ REG_C_2,
+ REG_C_3,
+ REG_C_4,
+ REG_C_5,
+ REG_C_6,
+ REG_C_7,
+};
+
+/* Private rte flow items. */
+enum mlx5_rte_flow_item_type {
+ MLX5_RTE_FLOW_ITEM_TYPE_END = INT_MIN,
+ MLX5_RTE_FLOW_ITEM_TYPE_TAG,
+};
+
+/* Private rte flow actions. */
+enum mlx5_rte_flow_action_type {
+ MLX5_RTE_FLOW_ACTION_TYPE_END = INT_MIN,
+ MLX5_RTE_FLOW_ACTION_TYPE_TAG,
+};
+
+/* Matches on selected register. */
+struct mlx5_rte_flow_item_tag {
+ uint16_t id;
+ rte_be32_t data;
+};
+
+/* Modify selected register. */
+struct mlx5_rte_flow_action_set_tag {
+ uint16_t id;
+ rte_be32_t data;
+};
+
/* Pattern outer Layer bits. */
#define MLX5_FLOW_LAYER_OUTER_L2 (1u << 0)
#define MLX5_FLOW_LAYER_OUTER_L3_IPV4 (1u << 1)
/* General pattern items bits. */
#define MLX5_FLOW_ITEM_METADATA (1u << 16)
#define MLX5_FLOW_ITEM_PORT_ID (1u << 17)
+#define MLX5_FLOW_ITEM_TAG (1u << 18)
/* Pattern MISC bits. */
-#define MLX5_FLOW_LAYER_ICMP (1u << 18)
-#define MLX5_FLOW_LAYER_ICMP6 (1u << 19)
-#define MLX5_FLOW_LAYER_GRE_KEY (1u << 20)
+#define MLX5_FLOW_LAYER_ICMP (1u << 19)
+#define MLX5_FLOW_LAYER_ICMP6 (1u << 20)
+#define MLX5_FLOW_LAYER_GRE_KEY (1u << 21)
/* Pattern tunnel Layer bits (continued). */
#define MLX5_FLOW_LAYER_IPIP (1u << 21)
#define MLX5_FLOW_ACTION_DEC_TCP_SEQ (1u << 29)
#define MLX5_FLOW_ACTION_INC_TCP_ACK (1u << 30)
#define MLX5_FLOW_ACTION_DEC_TCP_ACK (1u << 31)
+#define MLX5_FLOW_ACTION_SET_TAG (1ull << 32)
#define MLX5_FLOW_FATE_ACTIONS \
(MLX5_FLOW_ACTION_DROP | MLX5_FLOW_ACTION_QUEUE | \
MLX5_FLOW_ACTION_DEC_TCP_SEQ | \
MLX5_FLOW_ACTION_INC_TCP_ACK | \
MLX5_FLOW_ACTION_DEC_TCP_ACK | \
- MLX5_FLOW_ACTION_OF_SET_VLAN_VID)
+ MLX5_FLOW_ACTION_OF_SET_VLAN_VID | \
+ MLX5_FLOW_ACTION_SET_TAG)
#define MLX5_FLOW_VLAN_ACTIONS (MLX5_FLOW_ACTION_OF_POP_VLAN | \
MLX5_FLOW_ACTION_OF_PUSH_VLAN)
MLX5_MODIFICATION_TYPE_ADD, error);
}
+static enum mlx5_modification_field reg_to_field[] = {
+ [REG_A] = MLX5_MODI_META_DATA_REG_A,
+ [REG_B] = MLX5_MODI_META_DATA_REG_B,
+ [REG_C_0] = MLX5_MODI_META_REG_C_0,
+ [REG_C_1] = MLX5_MODI_META_REG_C_1,
+ [REG_C_2] = MLX5_MODI_META_REG_C_2,
+ [REG_C_3] = MLX5_MODI_META_REG_C_3,
+ [REG_C_4] = MLX5_MODI_META_REG_C_4,
+ [REG_C_5] = MLX5_MODI_META_REG_C_5,
+ [REG_C_6] = MLX5_MODI_META_REG_C_6,
+ [REG_C_7] = MLX5_MODI_META_REG_C_7,
+};
+
+/**
+ * Convert register set to DV specification.
+ *
+ * @param[in,out] resource
+ * Pointer to the modify-header resource.
+ * @param[in] action
+ * Pointer to action specification.
+ * @param[out] error
+ * Pointer to the error structure.
+ *
+ * @return
+ * 0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+static int
+flow_dv_convert_action_set_reg
+ (struct mlx5_flow_dv_modify_hdr_resource *resource,
+ const struct rte_flow_action *action,
+ struct rte_flow_error *error)
+{
+ const struct mlx5_rte_flow_action_set_tag *conf = (action->conf);
+ struct mlx5_modification_cmd *actions = resource->actions;
+ uint32_t i = resource->actions_num;
+
+ if (i >= MLX5_MODIFY_NUM)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "too many items to modify");
+ actions[i].action_type = MLX5_MODIFICATION_TYPE_SET;
+ actions[i].field = reg_to_field[conf->id];
+ actions[i].data0 = rte_cpu_to_be_32(actions[i].data0);
+ actions[i].data1 = conf->data;
+ ++i;
+ resource->actions_num = i;
+ if (!resource->actions_num)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION, NULL,
+ "invalid modification flow item");
+ return 0;
+}
+
/**
* Validate META item.
*
MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0, value);
}
+/**
+ * Add tag item to matcher
+ *
+ * @param[in, out] matcher
+ * Flow matcher.
+ * @param[in, out] key
+ * Flow matcher value.
+ * @param[in] item
+ * Flow pattern to translate.
+ */
+static void
+flow_dv_translate_item_tag(void *matcher, void *key,
+ const struct rte_flow_item *item)
+{
+ void *misc2_m =
+ MLX5_ADDR_OF(fte_match_param, matcher, misc_parameters_2);
+ void *misc2_v =
+ MLX5_ADDR_OF(fte_match_param, key, misc_parameters_2);
+ const struct mlx5_rte_flow_item_tag *tag_v = item->spec;
+ const struct mlx5_rte_flow_item_tag *tag_m = item->mask;
+ enum modify_reg reg = tag_v->id;
+ rte_be32_t value = tag_v->data;
+ rte_be32_t mask = tag_m->data;
+
+ switch (reg) {
+ case REG_A:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_a,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_a,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_B:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_b,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_b,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_0:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_0,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_0,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_1:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_1,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_1,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_2:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_2,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_2,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_3:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_3,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_3,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_4:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_4,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_4,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_5:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_5,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_5,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_6:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_6,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_6,
+ rte_be_to_cpu_32(value));
+ break;
+ case REG_C_7:
+ MLX5_SET(fte_match_set_misc2, misc2_m, metadata_reg_c_7,
+ rte_be_to_cpu_32(mask));
+ MLX5_SET(fte_match_set_misc2, misc2_v, metadata_reg_c_7,
+ rte_be_to_cpu_32(value));
+ break;
+ }
+}
+
/**
* Add source vport match to the specified matcher.
*
struct mlx5_flow_tbl_resource *tbl;
uint32_t port_id = 0;
struct mlx5_flow_dv_port_id_action_resource port_id_resource;
+ int action_type = actions->type;
- switch (actions->type) {
+ switch (action_type) {
case RTE_FLOW_ACTION_TYPE_VOID:
break;
case RTE_FLOW_ACTION_TYPE_PORT_ID:
MLX5_FLOW_ACTION_INC_TCP_ACK :
MLX5_FLOW_ACTION_DEC_TCP_ACK;
break;
+ case MLX5_RTE_FLOW_ACTION_TYPE_TAG:
+ if (flow_dv_convert_action_set_reg(&res, actions,
+ error))
+ return -rte_errno;
+ action_flags |= MLX5_FLOW_ACTION_SET_TAG;
+ break;
case RTE_FLOW_ACTION_TYPE_END:
actions_end = true;
if (action_flags & MLX5_FLOW_MODIFY_HDR_ACTIONS) {
flow->actions = action_flags;
for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) {
int tunnel = !!(item_flags & MLX5_FLOW_LAYER_TUNNEL);
+ int item_type = items->type;
- switch (items->type) {
+ switch (item_type) {
case RTE_FLOW_ITEM_TYPE_PORT_ID:
flow_dv_translate_item_port_id(dev, match_mask,
match_value, items);
items, tunnel);
last_item = MLX5_FLOW_LAYER_ICMP6;
break;
+ case MLX5_RTE_FLOW_ITEM_TYPE_TAG:
+ flow_dv_translate_item_tag(match_mask, match_value,
+ items);
+ last_item = MLX5_FLOW_ITEM_TAG;
+ break;
default:
break;
}