@@ -316,6 +316,58 @@ struct mlx5_flow_tunnel_info {
},
};
+enum mlx5_feature_name {
+ MLX5_HAIRPIN_RX,
+ MLX5_HAIRPIN_TX,
+ MLX5_APPLICATION,
+};
+
+/**
+ * Translate tag ID to register.
+ *
+ * @param[in] dev
+ * Pointer to the Ethernet device structure.
+ * @param[in] feature
+ * The feature that request the register.
+ * @param[in] id
+ * The request register ID.
+ * @param[out] error
+ * Error description in case of any.
+ *
+ * @return
+ * The request register on success, a negative errno
+ * value otherwise and rte_errno is set.
+ */
+__rte_unused
+static enum modify_reg flow_get_reg_id(struct rte_eth_dev *dev,
+ enum mlx5_feature_name feature,
+ uint32_t id,
+ struct rte_flow_error *error)
+{
+ static enum modify_reg id2reg[] = {
+ [0] = REG_A,
+ [1] = REG_C_2,
+ [2] = REG_C_3,
+ [3] = REG_C_4,
+ [4] = REG_B,};
+
+ dev = (void *)dev;
+ switch (feature) {
+ case MLX5_HAIRPIN_RX:
+ return REG_B;
+ case MLX5_HAIRPIN_TX:
+ return REG_A;
+ case MLX5_APPLICATION:
+ if (id > 4)
+ return rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL, "invalid tag id");
+ return id2reg[id];
+ }
+ return rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
+ NULL, "invalid feature name");
+}
+
/**
* Discover the maximum number of priority available.
*
@@ -27,6 +27,43 @@
#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)
@@ -53,11 +90,12 @@
/* 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)
@@ -141,6 +179,7 @@
#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 | \
@@ -174,7 +213,8 @@
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)
@@ -724,6 +724,59 @@ struct field_modify_info modify_tcp[] = {
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.
*
@@ -4720,6 +4773,94 @@ struct field_modify_info modify_tcp[] = {
}
/**
+ * 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.
*
* @param[in, out] matcher
@@ -5305,8 +5446,9 @@ struct field_modify_info modify_tcp[] = {
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:
@@ -5621,6 +5763,12 @@ struct field_modify_info modify_tcp[] = {
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) {
@@ -5645,8 +5793,9 @@ struct field_modify_info modify_tcp[] = {
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);
@@ -5797,6 +5946,11 @@ struct field_modify_info modify_tcp[] = {
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;
}
@@ -628,7 +628,8 @@ struct mlx5_ifc_fte_match_set_misc2_bits {
u8 metadata_reg_c_1[0x20];
u8 metadata_reg_c_0[0x20];
u8 metadata_reg_a[0x20];
- u8 reserved_at_1a0[0x60];
+ u8 metadata_reg_b[0x20];
+ u8 reserved_at_1c0[0x40];
};
struct mlx5_ifc_fte_match_set_misc3_bits {