@@ -75,12 +75,14 @@ enum {
75
75
MLX5E_TC_FLOW_HAIRPIN_RSS = BIT (MLX5E_TC_FLOW_BASE + 4 ),
76
76
};
77
77
78
+ #define MLX5E_TC_MAX_SPLITS 1
79
+
78
80
struct mlx5e_tc_flow {
79
81
struct rhash_head node ;
80
82
struct mlx5e_priv * priv ;
81
83
u64 cookie ;
82
84
u8 flags ;
83
- struct mlx5_flow_handle * rule ;
85
+ struct mlx5_flow_handle * rule [ MLX5E_TC_MAX_SPLITS + 1 ] ;
84
86
struct list_head encap ; /* flows sharing the same encap ID */
85
87
struct list_head mod_hdr ; /* flows sharing the same mod hdr ID */
86
88
struct list_head hairpin ; /* flows sharing the same hairpin */
@@ -794,8 +796,8 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
794
796
struct mlx5_nic_flow_attr * attr = flow -> nic_attr ;
795
797
struct mlx5_fc * counter = NULL ;
796
798
797
- counter = mlx5_flow_rule_counter (flow -> rule );
798
- mlx5_del_flow_rules (flow -> rule );
799
+ counter = mlx5_flow_rule_counter (flow -> rule [ 0 ] );
800
+ mlx5_del_flow_rules (flow -> rule [ 0 ] );
799
801
mlx5_fc_destroy (priv -> mdev , counter );
800
802
801
803
if (!mlx5e_tc_num_filters (priv ) && priv -> fs .tc .t ) {
@@ -870,9 +872,18 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
870
872
rule = mlx5_eswitch_add_offloaded_rule (esw , & parse_attr -> spec , attr );
871
873
if (IS_ERR (rule ))
872
874
goto err_add_rule ;
875
+
876
+ if (attr -> mirror_count ) {
877
+ flow -> rule [1 ] = mlx5_eswitch_add_fwd_rule (esw , & parse_attr -> spec , attr );
878
+ if (IS_ERR (flow -> rule [1 ]))
879
+ goto err_fwd_rule ;
880
+ }
873
881
}
874
882
return rule ;
875
883
884
+ err_fwd_rule :
885
+ mlx5_eswitch_del_offloaded_rule (esw , rule , attr );
886
+ rule = flow -> rule [1 ];
876
887
err_add_rule :
877
888
if (attr -> action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR )
878
889
mlx5e_detach_mod_hdr (priv , flow );
@@ -893,7 +904,9 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
893
904
894
905
if (flow -> flags & MLX5E_TC_FLOW_OFFLOADED ) {
895
906
flow -> flags &= ~MLX5E_TC_FLOW_OFFLOADED ;
896
- mlx5_eswitch_del_offloaded_rule (esw , flow -> rule , attr );
907
+ if (attr -> mirror_count )
908
+ mlx5_eswitch_del_offloaded_rule (esw , flow -> rule [1 ], attr );
909
+ mlx5_eswitch_del_offloaded_rule (esw , flow -> rule [0 ], attr );
897
910
}
898
911
899
912
mlx5_eswitch_del_vlan_action (esw , attr );
@@ -929,13 +942,25 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
929
942
list_for_each_entry (flow , & e -> flows , encap ) {
930
943
esw_attr = flow -> esw_attr ;
931
944
esw_attr -> encap_id = e -> encap_id ;
932
- flow -> rule = mlx5_eswitch_add_offloaded_rule (esw , & esw_attr -> parse_attr -> spec , esw_attr );
933
- if (IS_ERR (flow -> rule )) {
934
- err = PTR_ERR (flow -> rule );
945
+ flow -> rule [ 0 ] = mlx5_eswitch_add_offloaded_rule (esw , & esw_attr -> parse_attr -> spec , esw_attr );
946
+ if (IS_ERR (flow -> rule [ 0 ] )) {
947
+ err = PTR_ERR (flow -> rule [ 0 ] );
935
948
mlx5_core_warn (priv -> mdev , "Failed to update cached encapsulation flow, %d\n" ,
936
949
err );
937
950
continue ;
938
951
}
952
+
953
+ if (esw_attr -> mirror_count ) {
954
+ flow -> rule [1 ] = mlx5_eswitch_add_fwd_rule (esw , & esw_attr -> parse_attr -> spec , esw_attr );
955
+ if (IS_ERR (flow -> rule [1 ])) {
956
+ mlx5_eswitch_del_offloaded_rule (esw , flow -> rule [0 ], esw_attr );
957
+ err = PTR_ERR (flow -> rule [1 ]);
958
+ mlx5_core_warn (priv -> mdev , "Failed to update cached mirror flow, %d\n" ,
959
+ err );
960
+ continue ;
961
+ }
962
+ }
963
+
939
964
flow -> flags |= MLX5E_TC_FLOW_OFFLOADED ;
940
965
}
941
966
}
@@ -948,8 +973,12 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
948
973
949
974
list_for_each_entry (flow , & e -> flows , encap ) {
950
975
if (flow -> flags & MLX5E_TC_FLOW_OFFLOADED ) {
976
+ struct mlx5_esw_flow_attr * attr = flow -> esw_attr ;
977
+
951
978
flow -> flags &= ~MLX5E_TC_FLOW_OFFLOADED ;
952
- mlx5_eswitch_del_offloaded_rule (esw , flow -> rule , flow -> esw_attr );
979
+ if (attr -> mirror_count )
980
+ mlx5_eswitch_del_offloaded_rule (esw , flow -> rule [1 ], attr );
981
+ mlx5_eswitch_del_offloaded_rule (esw , flow -> rule [0 ], attr );
953
982
}
954
983
}
955
984
@@ -984,7 +1013,7 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
984
1013
continue ;
985
1014
list_for_each_entry (flow , & e -> flows , encap ) {
986
1015
if (flow -> flags & MLX5E_TC_FLOW_OFFLOADED ) {
987
- counter = mlx5_flow_rule_counter (flow -> rule );
1016
+ counter = mlx5_flow_rule_counter (flow -> rule [ 0 ] );
988
1017
mlx5_fc_query_cached (counter , & bytes , & packets , & lastuse );
989
1018
if (time_after ((unsigned long )lastuse , nhe -> reported_lastuse )) {
990
1019
neigh_used = true;
@@ -2714,16 +2743,16 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
2714
2743
err = parse_tc_fdb_actions (priv , f -> exts , parse_attr , flow );
2715
2744
if (err < 0 )
2716
2745
goto err_free ;
2717
- flow -> rule = mlx5e_tc_add_fdb_flow (priv , parse_attr , flow );
2746
+ flow -> rule [ 0 ] = mlx5e_tc_add_fdb_flow (priv , parse_attr , flow );
2718
2747
} else {
2719
2748
err = parse_tc_nic_actions (priv , f -> exts , parse_attr , flow );
2720
2749
if (err < 0 )
2721
2750
goto err_free ;
2722
- flow -> rule = mlx5e_tc_add_nic_flow (priv , parse_attr , flow );
2751
+ flow -> rule [ 0 ] = mlx5e_tc_add_nic_flow (priv , parse_attr , flow );
2723
2752
}
2724
2753
2725
- if (IS_ERR (flow -> rule )) {
2726
- err = PTR_ERR (flow -> rule );
2754
+ if (IS_ERR (flow -> rule [ 0 ] )) {
2755
+ err = PTR_ERR (flow -> rule [ 0 ] );
2727
2756
if (err != - EAGAIN )
2728
2757
goto err_free ;
2729
2758
}
@@ -2796,7 +2825,7 @@ int mlx5e_stats_flower(struct mlx5e_priv *priv,
2796
2825
if (!(flow -> flags & MLX5E_TC_FLOW_OFFLOADED ))
2797
2826
return 0 ;
2798
2827
2799
- counter = mlx5_flow_rule_counter (flow -> rule );
2828
+ counter = mlx5_flow_rule_counter (flow -> rule [ 0 ] );
2800
2829
if (!counter )
2801
2830
return 0 ;
2802
2831
0 commit comments