@@ -5707,8 +5707,8 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5707
5707
struct mlx5_rte_flow_item_tag * tag_item_spec ;
5708
5708
struct mlx5_rte_flow_item_tag * tag_item_mask ;
5709
5709
uint32_t tag_id = 0 ;
5710
- struct rte_flow_item * vlan_item_dst = NULL ;
5711
- const struct rte_flow_item * vlan_item_src = NULL ;
5710
+ bool vlan_actions ;
5711
+ struct rte_flow_item * orig_sfx_items = sfx_items ;
5712
5712
const struct rte_flow_item * orig_items = items ;
5713
5713
struct rte_flow_action * hw_mtr_action ;
5714
5714
struct rte_flow_action * action_pre_head = NULL ;
@@ -5725,6 +5725,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5725
5725
5726
5726
/* Prepare the suffix subflow items. */
5727
5727
tag_item = sfx_items ++ ;
5728
+ tag_item -> type = (enum rte_flow_item_type )MLX5_RTE_FLOW_ITEM_TYPE_TAG ;
5728
5729
for (; items -> type != RTE_FLOW_ITEM_TYPE_END ; items ++ ) {
5729
5730
int item_type = items -> type ;
5730
5731
@@ -5747,10 +5748,13 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5747
5748
sfx_items ++ ;
5748
5749
break ;
5749
5750
case RTE_FLOW_ITEM_TYPE_VLAN :
5750
- /* Determine if copy vlan item below. */
5751
- vlan_item_src = items ;
5752
- vlan_item_dst = sfx_items ++ ;
5753
- vlan_item_dst -> type = RTE_FLOW_ITEM_TYPE_VOID ;
5751
+ /*
5752
+ * Copy VLAN items in case VLAN actions are performed.
5753
+ * If there are no VLAN actions, these items will be VOID.
5754
+ */
5755
+ memcpy (sfx_items , items , sizeof (* sfx_items ));
5756
+ sfx_items -> type = (enum rte_flow_item_type )MLX5_RTE_FLOW_ITEM_TYPE_VLAN ;
5757
+ sfx_items ++ ;
5754
5758
break ;
5755
5759
default :
5756
5760
break ;
@@ -5767,6 +5771,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5767
5771
tag_action = actions_pre ++ ;
5768
5772
}
5769
5773
/* Prepare the actions for prefix and suffix flow. */
5774
+ vlan_actions = false;
5770
5775
for (; actions -> type != RTE_FLOW_ACTION_TYPE_END ; actions ++ ) {
5771
5776
struct rte_flow_action * action_cur = NULL ;
5772
5777
@@ -5797,16 +5802,7 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5797
5802
break ;
5798
5803
case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN :
5799
5804
case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID :
5800
- if (vlan_item_dst && vlan_item_src ) {
5801
- memcpy (vlan_item_dst , vlan_item_src ,
5802
- sizeof (* vlan_item_dst ));
5803
- /*
5804
- * Convert to internal match item, it is used
5805
- * for vlan push and set vid.
5806
- */
5807
- vlan_item_dst -> type = (enum rte_flow_item_type )
5808
- MLX5_RTE_FLOW_ITEM_TYPE_VLAN ;
5809
- }
5805
+ vlan_actions = true;
5810
5806
break ;
5811
5807
case RTE_FLOW_ACTION_TYPE_COUNT :
5812
5808
if (fm -> def_policy )
@@ -5821,6 +5817,14 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5821
5817
actions_sfx ++ : actions_pre ++ ;
5822
5818
memcpy (action_cur , actions , sizeof (struct rte_flow_action ));
5823
5819
}
5820
+ /* If there are no VLAN actions, convert VLAN items to VOID in suffix flow items. */
5821
+ if (!vlan_actions ) {
5822
+ struct rte_flow_item * it = orig_sfx_items ;
5823
+
5824
+ for (; it -> type != RTE_FLOW_ITEM_TYPE_END ; it ++ )
5825
+ if (it -> type == (enum rte_flow_item_type )MLX5_RTE_FLOW_ITEM_TYPE_VLAN )
5826
+ it -> type = RTE_FLOW_ITEM_TYPE_VOID ;
5827
+ }
5824
5828
/* Add end action to the actions. */
5825
5829
actions_sfx -> type = RTE_FLOW_ACTION_TYPE_END ;
5826
5830
if (priv -> sh -> meter_aso_en ) {
@@ -5910,8 +5914,6 @@ flow_meter_split_prep(struct rte_eth_dev *dev,
5910
5914
tag_action -> type = (enum rte_flow_action_type )
5911
5915
MLX5_RTE_FLOW_ACTION_TYPE_TAG ;
5912
5916
tag_action -> conf = set_tag ;
5913
- tag_item -> type = (enum rte_flow_item_type )
5914
- MLX5_RTE_FLOW_ITEM_TYPE_TAG ;
5915
5917
tag_item -> spec = tag_item_spec ;
5916
5918
tag_item -> last = NULL ;
5917
5919
tag_item -> mask = tag_item_mask ;
@@ -6739,6 +6741,19 @@ flow_meter_create_drop_flow_with_org_pattern(struct rte_eth_dev *dev,
6739
6741
& drop_split_info , error );
6740
6742
}
6741
6743
6744
+ static int
6745
+ flow_count_vlan_items (const struct rte_flow_item items [])
6746
+ {
6747
+ int items_n = 0 ;
6748
+
6749
+ for (; items -> type != RTE_FLOW_ITEM_TYPE_END ; items ++ ) {
6750
+ if (items -> type == RTE_FLOW_ITEM_TYPE_VLAN ||
6751
+ items -> type == (enum rte_flow_item_type )MLX5_RTE_FLOW_ITEM_TYPE_VLAN )
6752
+ items_n ++ ;
6753
+ }
6754
+ return items_n ;
6755
+ }
6756
+
6742
6757
/**
6743
6758
* The splitting for meter feature.
6744
6759
*
@@ -6794,6 +6809,7 @@ flow_create_split_meter(struct rte_eth_dev *dev,
6794
6809
size_t act_size ;
6795
6810
size_t item_size ;
6796
6811
int actions_n = 0 ;
6812
+ int vlan_items_n = 0 ;
6797
6813
int ret = 0 ;
6798
6814
6799
6815
if (priv -> mtr_en )
@@ -6853,9 +6869,11 @@ flow_create_split_meter(struct rte_eth_dev *dev,
6853
6869
act_size = (sizeof (struct rte_flow_action ) *
6854
6870
(actions_n + METER_PREFIX_ACTION )) +
6855
6871
sizeof (struct mlx5_rte_flow_action_set_tag );
6856
- /* Suffix items: tag, vlan, port id, end. */
6857
- #define METER_SUFFIX_ITEM 4
6858
- item_size = sizeof (struct rte_flow_item ) * METER_SUFFIX_ITEM +
6872
+ /* Flow can have multiple VLAN items. Account for them in suffix items. */
6873
+ vlan_items_n = flow_count_vlan_items (items );
6874
+ /* Suffix items: tag, [vlans], port id, end. */
6875
+ #define METER_SUFFIX_ITEM 3
6876
+ item_size = sizeof (struct rte_flow_item ) * (METER_SUFFIX_ITEM + vlan_items_n ) +
6859
6877
sizeof (struct mlx5_rte_flow_item_tag ) * 2 ;
6860
6878
sfx_actions = mlx5_malloc (MLX5_MEM_ZERO , (act_size + item_size ),
6861
6879
0 , SOCKET_ID_ANY );
0 commit comments