22/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
33
44#include "fs_core.h"
5+ #include "fs_cmd.h"
6+ #include "en.h"
57#include "lib/ipsec_fs_roce.h"
68#include "mlx5_core.h"
79#include <linux/random.h>
@@ -25,6 +27,8 @@ struct mlx5_ipsec_tx_roce {
2527 struct mlx5_flow_group * g ;
2628 struct mlx5_flow_table * ft ;
2729 struct mlx5_flow_handle * rule ;
30+ struct mlx5_flow_table * goto_alias_ft ;
31+ u32 alias_id ;
2832 struct mlx5_flow_namespace * ns ;
2933};
3034
@@ -187,9 +191,200 @@ static int ipsec_fs_roce_tx_rule_setup(struct mlx5_core_dev *mdev,
187191 return err ;
188192}
189193
190- void mlx5_ipsec_fs_roce_tx_destroy (struct mlx5_ipsec_fs * ipsec_roce )
194+ static int ipsec_fs_roce_tx_mpv_rule_setup (struct mlx5_core_dev * mdev ,
195+ struct mlx5_ipsec_tx_roce * roce ,
196+ struct mlx5_flow_table * pol_ft )
191197{
198+ struct mlx5_flow_destination dst = {};
199+ MLX5_DECLARE_FLOW_ACT (flow_act );
200+ struct mlx5_flow_handle * rule ;
201+ struct mlx5_flow_spec * spec ;
202+ int err = 0 ;
203+
204+ spec = kvzalloc (sizeof (* spec ), GFP_KERNEL );
205+ if (!spec )
206+ return - ENOMEM ;
207+
208+ spec -> match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS ;
209+ MLX5_SET_TO_ONES (fte_match_param , spec -> match_criteria , misc_parameters .source_vhca_port );
210+ MLX5_SET (fte_match_param , spec -> match_value , misc_parameters .source_vhca_port ,
211+ MLX5_CAP_GEN (mdev , native_port_num ));
212+
213+ flow_act .action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST ;
214+ dst .type = MLX5_FLOW_DESTINATION_TYPE_TABLE_TYPE ;
215+ dst .ft = roce -> goto_alias_ft ;
216+ rule = mlx5_add_flow_rules (roce -> ft , spec , & flow_act , & dst , 1 );
217+ if (IS_ERR (rule )) {
218+ err = PTR_ERR (rule );
219+ mlx5_core_err (mdev , "Fail to add TX RoCE IPsec rule err=%d\n" ,
220+ err );
221+ goto out ;
222+ }
223+ roce -> rule = rule ;
224+
225+ /* No need for miss rule, since on miss we go to next PRIO, in which
226+ * if master is configured, he will catch the traffic to go to his
227+ * encryption table.
228+ */
229+
230+ out :
231+ kvfree (spec );
232+ return err ;
233+ }
234+
235+ #define MLX5_TX_ROCE_GROUP_SIZE BIT(0)
236+ #define MLX5_IPSEC_RDMA_TX_FT_LEVEL 0
237+ #define MLX5_IPSEC_NIC_GOTO_ALIAS_FT_LEVEL 3 /* Since last used level in NIC ipsec is 2 */
238+
239+ static int ipsec_fs_roce_tx_mpv_create_ft (struct mlx5_core_dev * mdev ,
240+ struct mlx5_ipsec_tx_roce * roce ,
241+ struct mlx5_flow_table * pol_ft ,
242+ struct mlx5e_priv * peer_priv )
243+ {
244+ struct mlx5_flow_namespace * roce_ns , * nic_ns ;
245+ struct mlx5_flow_table_attr ft_attr = {};
246+ struct mlx5_flow_table next_ft ;
247+ struct mlx5_flow_table * ft ;
248+ int err ;
249+
250+ roce_ns = mlx5_get_flow_namespace (peer_priv -> mdev , MLX5_FLOW_NAMESPACE_RDMA_TX_IPSEC );
251+ if (!roce_ns )
252+ return - EOPNOTSUPP ;
253+
254+ nic_ns = mlx5_get_flow_namespace (peer_priv -> mdev , MLX5_FLOW_NAMESPACE_EGRESS_IPSEC );
255+ if (!nic_ns )
256+ return - EOPNOTSUPP ;
257+
258+ err = ipsec_fs_create_aliased_ft (mdev , peer_priv -> mdev , pol_ft , & roce -> alias_id );
259+ if (err )
260+ return err ;
261+
262+ next_ft .id = roce -> alias_id ;
263+ ft_attr .max_fte = 1 ;
264+ ft_attr .next_ft = & next_ft ;
265+ ft_attr .level = MLX5_IPSEC_NIC_GOTO_ALIAS_FT_LEVEL ;
266+ ft_attr .flags = MLX5_FLOW_TABLE_UNMANAGED ;
267+ ft = mlx5_create_flow_table (nic_ns , & ft_attr );
268+ if (IS_ERR (ft )) {
269+ err = PTR_ERR (ft );
270+ mlx5_core_err (mdev , "Fail to create RoCE IPsec goto alias ft err=%d\n" , err );
271+ goto destroy_alias ;
272+ }
273+
274+ roce -> goto_alias_ft = ft ;
275+
276+ memset (& ft_attr , 0 , sizeof (ft_attr ));
277+ ft_attr .max_fte = 1 ;
278+ ft_attr .level = MLX5_IPSEC_RDMA_TX_FT_LEVEL ;
279+ ft = mlx5_create_flow_table (roce_ns , & ft_attr );
280+ if (IS_ERR (ft )) {
281+ err = PTR_ERR (ft );
282+ mlx5_core_err (mdev , "Fail to create RoCE IPsec tx ft err=%d\n" , err );
283+ goto destroy_alias_ft ;
284+ }
285+
286+ roce -> ft = ft ;
287+
288+ return 0 ;
289+
290+ destroy_alias_ft :
291+ mlx5_destroy_flow_table (roce -> goto_alias_ft );
292+ destroy_alias :
293+ mlx5_cmd_alias_obj_destroy (peer_priv -> mdev , roce -> alias_id ,
294+ MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS );
295+ return err ;
296+ }
297+
298+ static int ipsec_fs_roce_tx_mpv_create_group_rules (struct mlx5_core_dev * mdev ,
299+ struct mlx5_ipsec_tx_roce * roce ,
300+ struct mlx5_flow_table * pol_ft ,
301+ u32 * in )
302+ {
303+ struct mlx5_flow_group * g ;
304+ int ix = 0 ;
305+ int err ;
306+ u8 * mc ;
307+
308+ mc = MLX5_ADDR_OF (create_flow_group_in , in , match_criteria );
309+ MLX5_SET_TO_ONES (fte_match_param , mc , misc_parameters .source_vhca_port );
310+ MLX5_SET_CFG (in , match_criteria_enable , MLX5_MATCH_MISC_PARAMETERS );
311+
312+ MLX5_SET_CFG (in , start_flow_index , ix );
313+ ix += MLX5_TX_ROCE_GROUP_SIZE ;
314+ MLX5_SET_CFG (in , end_flow_index , ix - 1 );
315+ g = mlx5_create_flow_group (roce -> ft , in );
316+ if (IS_ERR (g )) {
317+ err = PTR_ERR (g );
318+ mlx5_core_err (mdev , "Fail to create RoCE IPsec tx group err=%d\n" , err );
319+ return err ;
320+ }
321+ roce -> g = g ;
322+
323+ err = ipsec_fs_roce_tx_mpv_rule_setup (mdev , roce , pol_ft );
324+ if (err ) {
325+ mlx5_core_err (mdev , "Fail to create RoCE IPsec tx rules err=%d\n" , err );
326+ goto destroy_group ;
327+ }
328+
329+ return 0 ;
330+
331+ destroy_group :
332+ mlx5_destroy_flow_group (roce -> g );
333+ return err ;
334+ }
335+
336+ static int ipsec_fs_roce_tx_mpv_create (struct mlx5_core_dev * mdev ,
337+ struct mlx5_ipsec_fs * ipsec_roce ,
338+ struct mlx5_flow_table * pol_ft ,
339+ u32 * in )
340+ {
341+ struct mlx5_devcom_comp_dev * tmp = NULL ;
342+ struct mlx5_ipsec_tx_roce * roce ;
343+ struct mlx5e_priv * peer_priv ;
344+ int err ;
345+
346+ if (!mlx5_devcom_for_each_peer_begin (* ipsec_roce -> devcom ))
347+ return - EOPNOTSUPP ;
348+
349+ peer_priv = mlx5_devcom_get_next_peer_data (* ipsec_roce -> devcom , & tmp );
350+ if (!peer_priv ) {
351+ err = - EOPNOTSUPP ;
352+ goto release_peer ;
353+ }
354+
355+ roce = & ipsec_roce -> tx ;
356+
357+ err = ipsec_fs_roce_tx_mpv_create_ft (mdev , roce , pol_ft , peer_priv );
358+ if (err ) {
359+ mlx5_core_err (mdev , "Fail to create RoCE IPsec tables err=%d\n" , err );
360+ goto release_peer ;
361+ }
362+
363+ err = ipsec_fs_roce_tx_mpv_create_group_rules (mdev , roce , pol_ft , in );
364+ if (err ) {
365+ mlx5_core_err (mdev , "Fail to create RoCE IPsec tx group/rule err=%d\n" , err );
366+ goto destroy_tables ;
367+ }
368+
369+ mlx5_devcom_for_each_peer_end (* ipsec_roce -> devcom );
370+ return 0 ;
371+
372+ destroy_tables :
373+ mlx5_destroy_flow_table (roce -> ft );
374+ mlx5_destroy_flow_table (roce -> goto_alias_ft );
375+ mlx5_cmd_alias_obj_destroy (peer_priv -> mdev , roce -> alias_id ,
376+ MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS );
377+ release_peer :
378+ mlx5_devcom_for_each_peer_end (* ipsec_roce -> devcom );
379+ return err ;
380+ }
381+
382+ void mlx5_ipsec_fs_roce_tx_destroy (struct mlx5_ipsec_fs * ipsec_roce ,
383+ struct mlx5_core_dev * mdev )
384+ {
385+ struct mlx5_devcom_comp_dev * tmp = NULL ;
192386 struct mlx5_ipsec_tx_roce * tx_roce ;
387+ struct mlx5e_priv * peer_priv ;
193388
194389 if (!ipsec_roce )
195390 return ;
@@ -199,9 +394,24 @@ void mlx5_ipsec_fs_roce_tx_destroy(struct mlx5_ipsec_fs *ipsec_roce)
199394 mlx5_del_flow_rules (tx_roce -> rule );
200395 mlx5_destroy_flow_group (tx_roce -> g );
201396 mlx5_destroy_flow_table (tx_roce -> ft );
202- }
203397
204- #define MLX5_TX_ROCE_GROUP_SIZE BIT(0)
398+ if (!mlx5_core_is_mp_slave (mdev ))
399+ return ;
400+
401+ if (!mlx5_devcom_for_each_peer_begin (* ipsec_roce -> devcom ))
402+ return ;
403+
404+ peer_priv = mlx5_devcom_get_next_peer_data (* ipsec_roce -> devcom , & tmp );
405+ if (!peer_priv ) {
406+ mlx5_devcom_for_each_peer_end (* ipsec_roce -> devcom );
407+ return ;
408+ }
409+
410+ mlx5_destroy_flow_table (tx_roce -> goto_alias_ft );
411+ mlx5_cmd_alias_obj_destroy (peer_priv -> mdev , tx_roce -> alias_id ,
412+ MLX5_GENERAL_OBJECT_TYPES_FLOW_TABLE_ALIAS );
413+ mlx5_devcom_for_each_peer_end (* ipsec_roce -> devcom );
414+ }
205415
206416int mlx5_ipsec_fs_roce_tx_create (struct mlx5_core_dev * mdev ,
207417 struct mlx5_ipsec_fs * ipsec_roce ,
@@ -224,7 +434,14 @@ int mlx5_ipsec_fs_roce_tx_create(struct mlx5_core_dev *mdev,
224434 if (!in )
225435 return - ENOMEM ;
226436
437+ if (mlx5_core_is_mp_slave (mdev )) {
438+ err = ipsec_fs_roce_tx_mpv_create (mdev , ipsec_roce , pol_ft , in );
439+ goto free_in ;
440+ }
441+
227442 ft_attr .max_fte = 1 ;
443+ ft_attr .prio = 1 ;
444+ ft_attr .level = MLX5_IPSEC_RDMA_TX_FT_LEVEL ;
228445 ft = mlx5_create_flow_table (roce -> ns , & ft_attr );
229446 if (IS_ERR (ft )) {
230447 err = PTR_ERR (ft );
0 commit comments