33
44#include <linux/mlx5/fs.h>
55#include "eswitch.h"
6+ #include "fs_core.h"
67
78struct mlx5_termtbl_handle {
89 struct hlist_node termtbl_hlist ;
@@ -28,6 +29,10 @@ mlx5_eswitch_termtbl_hash(struct mlx5_flow_act *flow_act,
2829 sizeof (dest -> vport .num ), hash );
2930 hash = jhash ((const void * )& dest -> vport .vhca_id ,
3031 sizeof (dest -> vport .num ), hash );
32+ if (dest -> vport .pkt_reformat )
33+ hash = jhash (dest -> vport .pkt_reformat ,
34+ sizeof (* dest -> vport .pkt_reformat ),
35+ hash );
3136 return hash ;
3237}
3338
@@ -37,11 +42,19 @@ mlx5_eswitch_termtbl_cmp(struct mlx5_flow_act *flow_act1,
3742 struct mlx5_flow_act * flow_act2 ,
3843 struct mlx5_flow_destination * dest2 )
3944{
40- return flow_act1 -> action != flow_act2 -> action ||
41- dest1 -> vport .num != dest2 -> vport .num ||
42- dest1 -> vport .vhca_id != dest2 -> vport .vhca_id ||
43- memcmp (& flow_act1 -> vlan , & flow_act2 -> vlan ,
44- sizeof (flow_act1 -> vlan ));
45+ int ret ;
46+
47+ ret = flow_act1 -> action != flow_act2 -> action ||
48+ dest1 -> vport .num != dest2 -> vport .num ||
49+ dest1 -> vport .vhca_id != dest2 -> vport .vhca_id ||
50+ memcmp (& flow_act1 -> vlan , & flow_act2 -> vlan ,
51+ sizeof (flow_act1 -> vlan ));
52+ if (ret )
53+ return ret ;
54+
55+ return dest1 -> vport .pkt_reformat && dest2 -> vport .pkt_reformat ?
56+ memcmp (dest1 -> vport .pkt_reformat , dest2 -> vport .pkt_reformat ,
57+ sizeof (* dest1 -> vport .pkt_reformat )) : 0 ;
4558}
4659
4760static int
@@ -62,7 +75,8 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev,
6275 /* As this is the terminating action then the termination table is the
6376 * same prio as the slow path
6477 */
65- ft_attr .flags = MLX5_FLOW_TABLE_TERMINATION ;
78+ ft_attr .flags = MLX5_FLOW_TABLE_TERMINATION |
79+ MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT ;
6680 ft_attr .prio = FDB_SLOW_PATH ;
6781 ft_attr .max_fte = 1 ;
6882 ft_attr .autogroup .max_num_groups = 1 ;
@@ -74,7 +88,6 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev,
7488
7589 tt -> rule = mlx5_add_flow_rules (tt -> termtbl , NULL , flow_act ,
7690 & tt -> dest , 1 );
77-
7891 if (IS_ERR (tt -> rule )) {
7992 esw_warn (dev , "Failed to create termination table rule\n" );
8093 goto add_flow_err ;
@@ -92,15 +105,15 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev,
92105static struct mlx5_termtbl_handle *
93106mlx5_eswitch_termtbl_get_create (struct mlx5_eswitch * esw ,
94107 struct mlx5_flow_act * flow_act ,
95- struct mlx5_flow_destination * dest )
108+ struct mlx5_flow_destination * dest ,
109+ struct mlx5_esw_flow_attr * attr )
96110{
97111 struct mlx5_termtbl_handle * tt ;
98112 bool found = false;
99113 u32 hash_key ;
100114 int err ;
101115
102116 mutex_lock (& esw -> offloads .termtbl_mutex );
103-
104117 hash_key = mlx5_eswitch_termtbl_hash (flow_act , dest );
105118 hash_for_each_possible (esw -> offloads .termtbl_tbl , tt ,
106119 termtbl_hlist , hash_key ) {
@@ -122,6 +135,7 @@ mlx5_eswitch_termtbl_get_create(struct mlx5_eswitch *esw,
122135 tt -> dest .type = MLX5_FLOW_DESTINATION_TYPE_VPORT ;
123136 tt -> dest .vport .num = dest -> vport .num ;
124137 tt -> dest .vport .vhca_id = dest -> vport .vhca_id ;
138+ tt -> dest .vport .flags = dest -> vport .flags ;
125139 memcpy (& tt -> flow_act , flow_act , sizeof (* flow_act ));
126140
127141 err = mlx5_eswitch_termtbl_create (esw -> dev , tt , flow_act );
@@ -156,25 +170,44 @@ mlx5_eswitch_termtbl_put(struct mlx5_eswitch *esw,
156170 }
157171}
158172
173+ static bool mlx5_eswitch_termtbl_is_encap_reformat (struct mlx5_pkt_reformat * rt )
174+ {
175+ switch (rt -> reformat_type ) {
176+ case MLX5_REFORMAT_TYPE_L2_TO_VXLAN :
177+ case MLX5_REFORMAT_TYPE_L2_TO_NVGRE :
178+ case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL :
179+ case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL :
180+ return true;
181+ default :
182+ return false;
183+ }
184+ }
185+
159186static void
160187mlx5_eswitch_termtbl_actions_move (struct mlx5_flow_act * src ,
161188 struct mlx5_flow_act * dst )
162189{
163- if (!(src -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ))
164- return ;
165-
166- src -> action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ;
167- dst -> action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ;
168- memcpy (& dst -> vlan [0 ], & src -> vlan [0 ], sizeof (src -> vlan [0 ]));
169- memset (& src -> vlan [0 ], 0 , sizeof (src -> vlan [0 ]));
170-
171- if (!(src -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ))
172- return ;
190+ if (src -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ) {
191+ src -> action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ;
192+ dst -> action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ;
193+ memcpy (& dst -> vlan [0 ], & src -> vlan [0 ], sizeof (src -> vlan [0 ]));
194+ memset (& src -> vlan [0 ], 0 , sizeof (src -> vlan [0 ]));
195+
196+ if (src -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ) {
197+ src -> action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ;
198+ dst -> action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ;
199+ memcpy (& dst -> vlan [1 ], & src -> vlan [1 ], sizeof (src -> vlan [1 ]));
200+ memset (& src -> vlan [1 ], 0 , sizeof (src -> vlan [1 ]));
201+ }
202+ }
173203
174- src -> action &= ~MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ;
175- dst -> action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 ;
176- memcpy (& dst -> vlan [1 ], & src -> vlan [1 ], sizeof (src -> vlan [1 ]));
177- memset (& src -> vlan [1 ], 0 , sizeof (src -> vlan [1 ]));
204+ if (src -> action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT &&
205+ mlx5_eswitch_termtbl_is_encap_reformat (src -> pkt_reformat )) {
206+ src -> action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT ;
207+ dst -> action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT ;
208+ dst -> pkt_reformat = src -> pkt_reformat ;
209+ src -> pkt_reformat = NULL ;
210+ }
178211}
179212
180213static bool mlx5_eswitch_offload_is_uplink_port (const struct mlx5_eswitch * esw ,
@@ -199,13 +232,23 @@ mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw,
199232 struct mlx5_flow_act * flow_act ,
200233 struct mlx5_flow_spec * spec )
201234{
235+ int i ;
236+
202237 if (!MLX5_CAP_ESW_FLOWTABLE_FDB (esw -> dev , termination_table ) ||
203- attr -> flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH )
238+ attr -> flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH ||
239+ !mlx5_eswitch_offload_is_uplink_port (esw , spec ))
204240 return false;
205241
206242 /* push vlan on RX */
207- return (flow_act -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH ) &&
208- mlx5_eswitch_offload_is_uplink_port (esw , spec );
243+ if (flow_act -> action & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH )
244+ return true;
245+
246+ /* hairpin */
247+ for (i = attr -> split_count ; i < attr -> out_count ; i ++ )
248+ if (attr -> dests [i ].rep -> vport == MLX5_VPORT_UPLINK )
249+ return true;
250+
251+ return false;
209252}
210253
211254struct mlx5_flow_handle *
@@ -235,7 +278,7 @@ mlx5_eswitch_add_termtbl_rule(struct mlx5_eswitch *esw,
235278
236279 /* get the terminating table for the action list */
237280 tt = mlx5_eswitch_termtbl_get_create (esw , & term_tbl_act ,
238- & dest [i ]);
281+ & dest [i ], attr );
239282 if (IS_ERR (tt )) {
240283 esw_warn (esw -> dev , "Failed to create termination table\n" );
241284 goto revert_changes ;
0 commit comments