From 50f576d657d78e87a3eac597353d236969969c17 Mon Sep 17 00:00:00 2001 From: Suanming Mou Date: Thu, 20 Feb 2020 09:45:44 +0200 Subject: [PATCH] net/mlx5: fix VLAN actions in meter Meter suffix subflow only has the port id and tag match item, if VLAN push and set VLAN id actions exist in the suffix subflow, the user defined VLAN items is required for the actions to set a correct VLAN id. Currently, the VLAN item stays in the meter prefix subflow. Without the VLAN item, VLAN id or pcp will not be inherited. Actions require the VLAN item as below: RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID Add a private VLAN item to copy the user defined VLAN item to the meter suffix subflow, so the suffix subflow will have the chance to get the correct original VLAN id and pcp value from the VLAN item. Fixes: 9ea9b049a960 ("net/mlx5: split meter flow") Cc: stable@dpdk.org Signed-off-by: Suanming Mou Acked-by: Matan Azrad --- drivers/net/mlx5/mlx5_flow.c | 153 +++++++++++++++----------------- drivers/net/mlx5/mlx5_flow.h | 4 + drivers/net/mlx5/mlx5_flow_dv.c | 14 +-- 3 files changed, 82 insertions(+), 89 deletions(-) diff --git a/drivers/net/mlx5/mlx5_flow.c b/drivers/net/mlx5/mlx5_flow.c index da60ce7578..49308e9c5d 100644 --- a/drivers/net/mlx5/mlx5_flow.c +++ b/drivers/net/mlx5/mlx5_flow.c @@ -2663,26 +2663,6 @@ mlx5_flow_validate(struct rte_eth_dev *dev, return 0; } -/** - * Get port id item from the item list. - * - * @param[in] item - * Pointer to the list of items. - * - * @return - * Pointer to the port id item if exist, else return NULL. - */ -static const struct rte_flow_item * -find_port_id_item(const struct rte_flow_item *item) -{ - MLX5_ASSERT(item); - for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) { - if (item->type == RTE_FLOW_ITEM_TYPE_PORT_ID) - return item; - } - return NULL; -} - /** * Get RSS action from the action list. * @@ -3502,6 +3482,10 @@ flow_create_split_inner(struct rte_eth_dev *dev, * * @param dev * Pointer to Ethernet device. + * @param[in] items + * Pattern specification (list terminated by the END pattern item). + * @param[out] sfx_items + * Suffix flow match items (list terminated by the END pattern item). * @param[in] actions * Associated actions (list terminated by the END action). * @param[out] actions_sfx @@ -3518,70 +3502,60 @@ flow_create_split_inner(struct rte_eth_dev *dev, */ static int flow_meter_split_prep(struct rte_eth_dev *dev, + const struct rte_flow_item items[], + struct rte_flow_item sfx_items[], const struct rte_flow_action actions[], struct rte_flow_action actions_sfx[], struct rte_flow_action actions_pre[]) { struct rte_flow_action *tag_action = NULL; + struct rte_flow_item *tag_item; struct mlx5_rte_flow_action_set_tag *set_tag; struct rte_flow_error error; const struct rte_flow_action_raw_encap *raw_encap; const struct rte_flow_action_raw_decap *raw_decap; + struct mlx5_rte_flow_item_tag *tag_spec; + struct mlx5_rte_flow_item_tag *tag_mask; uint32_t tag_id; + bool copy_vlan = false; /* Prepare the actions for prefix and suffix flow. */ for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) { + struct rte_flow_action **action_cur = NULL; + switch (actions->type) { case RTE_FLOW_ACTION_TYPE_METER: /* Add the extra tag action first. */ tag_action = actions_pre; tag_action->type = MLX5_RTE_FLOW_ACTION_TYPE_TAG; actions_pre++; - memcpy(actions_pre, actions, - sizeof(struct rte_flow_action)); - actions_pre++; + action_cur = &actions_pre; break; case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: case RTE_FLOW_ACTION_TYPE_NVGRE_DECAP: - memcpy(actions_pre, actions, - sizeof(struct rte_flow_action)); - actions_pre++; + action_cur = &actions_pre; break; case RTE_FLOW_ACTION_TYPE_RAW_ENCAP: raw_encap = actions->conf; - if (raw_encap->size > - (sizeof(struct rte_flow_item_eth) + - sizeof(struct rte_flow_item_ipv4))) { - memcpy(actions_sfx, actions, - sizeof(struct rte_flow_action)); - actions_sfx++; - } else { - rte_memcpy(actions_pre, actions, - sizeof(struct rte_flow_action)); - actions_pre++; - } + if (raw_encap->size < MLX5_ENCAPSULATION_DECISION_SIZE) + action_cur = &actions_pre; break; case RTE_FLOW_ACTION_TYPE_RAW_DECAP: raw_decap = actions->conf; - /* Size 0 decap means 50 bytes as vxlan decap. */ - if (raw_decap->size && (raw_decap->size < - (sizeof(struct rte_flow_item_eth) + - sizeof(struct rte_flow_item_ipv4)))) { - memcpy(actions_sfx, actions, - sizeof(struct rte_flow_action)); - actions_sfx++; - } else { - rte_memcpy(actions_pre, actions, - sizeof(struct rte_flow_action)); - actions_pre++; - } + if (raw_decap->size > MLX5_ENCAPSULATION_DECISION_SIZE) + action_cur = &actions_pre; + break; + case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN: + case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID: + copy_vlan = true; break; default: - memcpy(actions_sfx, actions, - sizeof(struct rte_flow_action)); - actions_sfx++; break; } + if (!action_cur) + action_cur = &actions_sfx; + memcpy(*action_cur, actions, sizeof(struct rte_flow_action)); + (*action_cur)++; } /* Add end action to the actions. */ actions_sfx->type = RTE_FLOW_ACTION_TYPE_END; @@ -3597,6 +3571,42 @@ flow_meter_split_prep(struct rte_eth_dev *dev, set_tag->data = tag_id << MLX5_MTR_COLOR_BITS; assert(tag_action); tag_action->conf = set_tag; + /* Prepare the suffix subflow items. */ + tag_item = sfx_items++; + for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { + int item_type = items->type; + + switch (item_type) { + case RTE_FLOW_ITEM_TYPE_PORT_ID: + memcpy(sfx_items, items, sizeof(*sfx_items)); + sfx_items++; + break; + case RTE_FLOW_ITEM_TYPE_VLAN: + if (copy_vlan) { + memcpy(sfx_items, items, sizeof(*sfx_items)); + /* + * Convert to internal match item, it is used + * for vlan push and set vid. + */ + sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_VLAN; + sfx_items++; + } + break; + default: + break; + } + } + sfx_items->type = RTE_FLOW_ITEM_TYPE_END; + sfx_items++; + tag_spec = (struct mlx5_rte_flow_item_tag *)sfx_items; + tag_spec->data = tag_id << MLX5_MTR_COLOR_BITS; + tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, &error); + tag_mask = tag_spec + 1; + tag_mask->data = 0xffffff00; + tag_item->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG; + tag_item->spec = tag_spec; + tag_item->last = NULL; + tag_item->mask = tag_mask; return tag_id; } @@ -4022,7 +4032,6 @@ flow_create_split_meter(struct rte_eth_dev *dev, struct rte_flow_action *sfx_actions = NULL; struct rte_flow_action *pre_actions = NULL; struct rte_flow_item *sfx_items = NULL; - const struct rte_flow_item *sfx_port_id_item; struct mlx5_flow *dev_flow = NULL; struct rte_flow_attr sfx_attr = *attr; uint32_t mtr = 0; @@ -4035,13 +4044,11 @@ flow_create_split_meter(struct rte_eth_dev *dev, if (priv->mtr_en) actions_n = flow_check_meter_action(actions, &mtr); if (mtr) { - struct mlx5_rte_flow_item_tag *tag_spec; - struct mlx5_rte_flow_item_tag *tag_mask; /* The five prefix actions: meter, decap, encap, tag, end. */ act_size = sizeof(struct rte_flow_action) * (actions_n + 5) + - sizeof(struct rte_flow_action_set_tag); - /* tag, end. */ -#define METER_SUFFIX_ITEM 3 + sizeof(struct mlx5_rte_flow_action_set_tag); + /* tag, vlan, port id, end. */ +#define METER_SUFFIX_ITEM 4 item_size = sizeof(struct rte_flow_item) * METER_SUFFIX_ITEM + sizeof(struct mlx5_rte_flow_item_tag) * 2; sfx_actions = rte_zmalloc(__func__, (act_size + item_size), 0); @@ -4050,9 +4057,12 @@ flow_create_split_meter(struct rte_eth_dev *dev, RTE_FLOW_ERROR_TYPE_ACTION, NULL, "no memory to split " "meter flow"); + sfx_items = (struct rte_flow_item *)((char *)sfx_actions + + act_size); pre_actions = sfx_actions + actions_n; - mtr_tag_id = flow_meter_split_prep(dev, actions, sfx_actions, - pre_actions); + mtr_tag_id = flow_meter_split_prep(dev, items, sfx_items, + actions, sfx_actions, + pre_actions); if (!mtr_tag_id) { ret = -rte_errno; goto exit; @@ -4066,29 +4076,6 @@ flow_create_split_meter(struct rte_eth_dev *dev, goto exit; } dev_flow->mtr_flow_id = mtr_tag_id; - /* Prepare the suffix flow match pattern. */ - sfx_items = (struct rte_flow_item *)((char *)sfx_actions + - act_size); - tag_spec = (struct mlx5_rte_flow_item_tag *)(sfx_items + - METER_SUFFIX_ITEM); - tag_spec->data = dev_flow->mtr_flow_id << MLX5_MTR_COLOR_BITS; - tag_spec->id = mlx5_flow_get_reg_id(dev, MLX5_MTR_SFX, 0, - error); - tag_mask = tag_spec + 1; - tag_mask->data = 0xffffff00; - sfx_items->type = MLX5_RTE_FLOW_ITEM_TYPE_TAG; - sfx_items->spec = tag_spec; - sfx_items->last = NULL; - sfx_items->mask = tag_mask; - sfx_items++; - sfx_port_id_item = find_port_id_item(items); - if (sfx_port_id_item) { - memcpy(sfx_items, sfx_port_id_item, - sizeof(*sfx_items)); - sfx_items++; - } - sfx_items->type = RTE_FLOW_ITEM_TYPE_END; - sfx_items -= sfx_port_id_item ? 2 : 1; /* Setting the sfx group atrr. */ sfx_attr.group = sfx_attr.transfer ? (MLX5_FLOW_TABLE_LEVEL_SUFFIX - 1) : diff --git a/drivers/net/mlx5/mlx5_flow.h b/drivers/net/mlx5/mlx5_flow.h index 791f3bd3e8..13c8589013 100644 --- a/drivers/net/mlx5/mlx5_flow.h +++ b/drivers/net/mlx5/mlx5_flow.h @@ -34,6 +34,7 @@ enum mlx5_rte_flow_item_type { MLX5_RTE_FLOW_ITEM_TYPE_END = INT_MIN, MLX5_RTE_FLOW_ITEM_TYPE_TAG, MLX5_RTE_FLOW_ITEM_TYPE_TX_QUEUE, + MLX5_RTE_FLOW_ITEM_TYPE_VLAN, }; /* Private (internal) rte flow actions. */ @@ -328,6 +329,9 @@ enum mlx5_feature_name { #define MLX5_GENEVE_OPT_LEN_0 14 #define MLX5_GENEVE_OPT_LEN_1 63 +#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_flow_item_eth) + \ + sizeof(struct rte_flow_item_ipv4)) + enum mlx5_flow_drv_type { MLX5_FLOW_TYPE_MIN, MLX5_FLOW_TYPE_DV, diff --git a/drivers/net/mlx5/mlx5_flow_dv.c b/drivers/net/mlx5/mlx5_flow_dv.c index ebd7a93ac3..3c6d90e349 100644 --- a/drivers/net/mlx5/mlx5_flow_dv.c +++ b/drivers/net/mlx5/mlx5_flow_dv.c @@ -54,8 +54,6 @@ #define MLX5DV_DR_ACTION_FLAGS_ROOT_LEVEL 1 #endif -#define MLX5_ENCAPSULATION_DECISION_SIZE (sizeof(struct rte_flow_item_eth) + \ - sizeof(struct rte_flow_item_ipv4)) /* VLAN header definitions */ #define MLX5DV_FLOW_VLAN_PCP_SHIFT 13 #define MLX5DV_FLOW_VLAN_PCP_MASK (0x7 << MLX5DV_FLOW_VLAN_PCP_SHIFT) @@ -1757,10 +1755,14 @@ flow_dev_get_vlan_info_from_items(const struct rte_flow_item *items, if (items == NULL) return; - for (; items->type != RTE_FLOW_ITEM_TYPE_END && - items->type != RTE_FLOW_ITEM_TYPE_VLAN; items++) - ; - if (items->type == RTE_FLOW_ITEM_TYPE_VLAN) { + for (; items->type != RTE_FLOW_ITEM_TYPE_END; items++) { + int type = items->type; + + if (type == RTE_FLOW_ITEM_TYPE_VLAN || + type == MLX5_RTE_FLOW_ITEM_TYPE_VLAN) + break; + } + if (items->type != RTE_FLOW_ITEM_TYPE_END) { const struct rte_flow_item_vlan *vlan_m = items->mask; const struct rte_flow_item_vlan *vlan_v = items->spec; -- 2.20.1