[dpdk-dev] [PATCH] net/mlx5: fix VLAN actions in meter

Raslan Darawsheh rasland at mellanox.com
Thu Feb 20 13:43:54 CET 2020


Hi,
> -----Original Message-----
> From: Suanming Mou <suanmingm at mellanox.com>
> Sent: Thursday, February 20, 2020 9:46 AM
> To: Slava Ovsiienko <viacheslavo at mellanox.com>; Matan Azrad
> <matan at mellanox.com>
> Cc: dev at dpdk.org; Raslan Darawsheh <rasland at mellanox.com>;
> stable at dpdk.org
> 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 at dpdk.org
> 
> Signed-off-by: Suanming Mou <suanmingm at mellanox.com>
> ---
>  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 e5d2e64..2a78c43 100644
> --- a/drivers/net/mlx5/mlx5_flow.c
> +++ b/drivers/net/mlx5/mlx5_flow.c
> @@ -2664,26 +2664,6 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>  }
> 
>  /**
> - * 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.
>   *
>   * @param[in] actions
> @@ -3502,6 +3482,10 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>   *
>   * @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 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>   */
>  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 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>  	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;
>  }
> 
> @@ -4023,7 +4033,6 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>  	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;
> @@ -4036,13 +4045,11 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>  	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);
> @@ -4051,9 +4058,12 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
> 
> 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;
> @@ -4067,29 +4077,6 @@ uint32_t mlx5_flow_adjust_priority(struct
> rte_eth_dev *dev, int32_t priority,
>  			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 791f3bd..13c8589 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 3fac288..2437e55 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 @@ struct field_modify_info modify_tcp[] = {
> 
>  	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;
> 
> --
> 1.8.3.1

Patch applied to next-net-mlx,

Kindest regards,
Raslan Darawsheh


More information about the dev mailing list