@@ -34,6 +34,12 @@ struct mlx5e_accel_fs_esp {
3434 struct mlx5e_accel_fs_esp_prot fs_prot [ACCEL_FS_ESP_NUM_TYPES ];
3535};
3636
37+ struct mlx5e_ipsec_tx {
38+ struct mlx5_flow_table * ft ;
39+ struct mutex mutex ; /* Protect IPsec TX steering */
40+ u32 refcnt ;
41+ };
42+
3743/* IPsec RX flow steering */
3844static enum mlx5e_traffic_types fs_esp2tt (enum accel_fs_esp_type i )
3945{
@@ -323,6 +329,77 @@ static void rx_ft_put(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
323329 mutex_unlock (& fs_prot -> prot_mutex );
324330}
325331
332+ /* IPsec TX flow steering */
333+ static int tx_create (struct mlx5e_priv * priv )
334+ {
335+ struct mlx5_flow_table_attr ft_attr = {};
336+ struct mlx5e_ipsec * ipsec = priv -> ipsec ;
337+ struct mlx5_flow_table * ft ;
338+ int err ;
339+
340+ priv -> fs .egress_ns =
341+ mlx5_get_flow_namespace (priv -> mdev ,
342+ MLX5_FLOW_NAMESPACE_EGRESS_KERNEL );
343+ if (!priv -> fs .egress_ns )
344+ return - EOPNOTSUPP ;
345+
346+ ft_attr .max_fte = NUM_IPSEC_FTE ;
347+ ft_attr .autogroup .max_num_groups = 1 ;
348+ ft = mlx5_create_auto_grouped_flow_table (priv -> fs .egress_ns , & ft_attr );
349+ if (IS_ERR (ft )) {
350+ err = PTR_ERR (ft );
351+ netdev_err (priv -> netdev , "fail to create ipsec tx ft err=%d\n" , err );
352+ return err ;
353+ }
354+ ipsec -> tx_fs -> ft = ft ;
355+ return 0 ;
356+ }
357+
358+ static void tx_destroy (struct mlx5e_priv * priv )
359+ {
360+ struct mlx5e_ipsec * ipsec = priv -> ipsec ;
361+
362+ if (IS_ERR_OR_NULL (ipsec -> tx_fs -> ft ))
363+ return ;
364+
365+ mlx5_destroy_flow_table (ipsec -> tx_fs -> ft );
366+ ipsec -> tx_fs -> ft = NULL ;
367+ }
368+
369+ static int tx_ft_get (struct mlx5e_priv * priv )
370+ {
371+ struct mlx5e_ipsec_tx * tx_fs = priv -> ipsec -> tx_fs ;
372+ int err = 0 ;
373+
374+ mutex_lock (& tx_fs -> mutex );
375+ if (tx_fs -> refcnt ++ )
376+ goto out ;
377+
378+ err = tx_create (priv );
379+ if (err ) {
380+ tx_fs -> refcnt -- ;
381+ goto out ;
382+ }
383+
384+ out :
385+ mutex_unlock (& tx_fs -> mutex );
386+ return err ;
387+ }
388+
389+ static void tx_ft_put (struct mlx5e_priv * priv )
390+ {
391+ struct mlx5e_ipsec_tx * tx_fs = priv -> ipsec -> tx_fs ;
392+
393+ mutex_lock (& tx_fs -> mutex );
394+ if (-- tx_fs -> refcnt )
395+ goto out ;
396+
397+ tx_destroy (priv );
398+
399+ out :
400+ mutex_unlock (& tx_fs -> mutex );
401+ }
402+
326403static void setup_fte_common (struct mlx5_accel_esp_xfrm_attrs * attrs ,
327404 u32 ipsec_obj_id ,
328405 struct mlx5_flow_spec * spec ,
@@ -457,6 +534,54 @@ static int rx_add_rule(struct mlx5e_priv *priv,
457534 return err ;
458535}
459536
537+ static int tx_add_rule (struct mlx5e_priv * priv ,
538+ struct mlx5_accel_esp_xfrm_attrs * attrs ,
539+ u32 ipsec_obj_id ,
540+ struct mlx5e_ipsec_rule * ipsec_rule )
541+ {
542+ struct mlx5_flow_act flow_act = {};
543+ struct mlx5_flow_handle * rule ;
544+ struct mlx5_flow_spec * spec ;
545+ int err = 0 ;
546+
547+ err = tx_ft_get (priv );
548+ if (err )
549+ return err ;
550+
551+ spec = kvzalloc (sizeof (* spec ), GFP_KERNEL );
552+ if (!spec ) {
553+ err = - ENOMEM ;
554+ goto out ;
555+ }
556+
557+ setup_fte_common (attrs , ipsec_obj_id , spec , & flow_act );
558+
559+ /* Add IPsec indicator in metadata_reg_a */
560+ spec -> match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2 ;
561+ MLX5_SET (fte_match_param , spec -> match_criteria , misc_parameters_2 .metadata_reg_a ,
562+ MLX5_ETH_WQE_FT_META_IPSEC );
563+ MLX5_SET (fte_match_param , spec -> match_value , misc_parameters_2 .metadata_reg_a ,
564+ MLX5_ETH_WQE_FT_META_IPSEC );
565+
566+ flow_act .action = MLX5_FLOW_CONTEXT_ACTION_ALLOW |
567+ MLX5_FLOW_CONTEXT_ACTION_IPSEC_ENCRYPT ;
568+ rule = mlx5_add_flow_rules (priv -> ipsec -> tx_fs -> ft , spec , & flow_act , NULL , 0 );
569+ if (IS_ERR (rule )) {
570+ err = PTR_ERR (rule );
571+ netdev_err (priv -> netdev , "fail to add ipsec rule attrs->action=0x%x, err=%d\n" ,
572+ attrs -> action , err );
573+ goto out ;
574+ }
575+
576+ ipsec_rule -> rule = rule ;
577+
578+ out :
579+ kvfree (spec );
580+ if (err )
581+ tx_ft_put (priv );
582+ return err ;
583+ }
584+
460585static void rx_del_rule (struct mlx5e_priv * priv ,
461586 struct mlx5_accel_esp_xfrm_attrs * attrs ,
462587 struct mlx5e_ipsec_rule * ipsec_rule )
@@ -470,15 +595,27 @@ static void rx_del_rule(struct mlx5e_priv *priv,
470595 rx_ft_put (priv , attrs -> is_ipv6 ? ACCEL_FS_ESP6 : ACCEL_FS_ESP4 );
471596}
472597
598+ static void tx_del_rule (struct mlx5e_priv * priv ,
599+ struct mlx5e_ipsec_rule * ipsec_rule )
600+ {
601+ mlx5_del_flow_rules (ipsec_rule -> rule );
602+ ipsec_rule -> rule = NULL ;
603+
604+ tx_ft_put (priv );
605+ }
606+
473607int mlx5e_accel_ipsec_fs_add_rule (struct mlx5e_priv * priv ,
474608 struct mlx5_accel_esp_xfrm_attrs * attrs ,
475609 u32 ipsec_obj_id ,
476610 struct mlx5e_ipsec_rule * ipsec_rule )
477611{
478- if (!priv -> ipsec -> rx_fs || attrs -> action != MLX5_ACCEL_ESP_ACTION_DECRYPT )
612+ if (!priv -> ipsec -> rx_fs )
479613 return - EOPNOTSUPP ;
480614
481- return rx_add_rule (priv , attrs , ipsec_obj_id , ipsec_rule );
615+ if (attrs -> action == MLX5_ACCEL_ESP_ACTION_DECRYPT )
616+ return rx_add_rule (priv , attrs , ipsec_obj_id , ipsec_rule );
617+ else
618+ return tx_add_rule (priv , attrs , ipsec_obj_id , ipsec_rule );
482619}
483620
484621void mlx5e_accel_ipsec_fs_del_rule (struct mlx5e_priv * priv ,
@@ -488,7 +625,18 @@ void mlx5e_accel_ipsec_fs_del_rule(struct mlx5e_priv *priv,
488625 if (!priv -> ipsec -> rx_fs )
489626 return ;
490627
491- rx_del_rule (priv , attrs , ipsec_rule );
628+ if (attrs -> action == MLX5_ACCEL_ESP_ACTION_DECRYPT )
629+ rx_del_rule (priv , attrs , ipsec_rule );
630+ else
631+ tx_del_rule (priv , ipsec_rule );
632+ }
633+
634+ static void fs_cleanup_tx (struct mlx5e_priv * priv )
635+ {
636+ mutex_destroy (& priv -> ipsec -> tx_fs -> mutex );
637+ WARN_ON (priv -> ipsec -> tx_fs -> refcnt );
638+ kfree (priv -> ipsec -> tx_fs );
639+ priv -> ipsec -> tx_fs = NULL ;
492640}
493641
494642static void fs_cleanup_rx (struct mlx5e_priv * priv )
@@ -507,6 +655,17 @@ static void fs_cleanup_rx(struct mlx5e_priv *priv)
507655 priv -> ipsec -> rx_fs = NULL ;
508656}
509657
658+ static int fs_init_tx (struct mlx5e_priv * priv )
659+ {
660+ priv -> ipsec -> tx_fs =
661+ kzalloc (sizeof (struct mlx5e_ipsec_tx ), GFP_KERNEL );
662+ if (!priv -> ipsec -> tx_fs )
663+ return - ENOMEM ;
664+
665+ mutex_init (& priv -> ipsec -> tx_fs -> mutex );
666+ return 0 ;
667+ }
668+
510669static int fs_init_rx (struct mlx5e_priv * priv )
511670{
512671 struct mlx5e_accel_fs_esp_prot * fs_prot ;
@@ -532,13 +691,24 @@ void mlx5e_accel_ipsec_fs_cleanup(struct mlx5e_priv *priv)
532691 if (!priv -> ipsec -> rx_fs )
533692 return ;
534693
694+ fs_cleanup_tx (priv );
535695 fs_cleanup_rx (priv );
536696}
537697
538698int mlx5e_accel_ipsec_fs_init (struct mlx5e_priv * priv )
539699{
700+ int err ;
701+
540702 if (!mlx5_is_ipsec_device (priv -> mdev ) || !priv -> ipsec )
541703 return - EOPNOTSUPP ;
542704
543- return fs_init_rx (priv );
705+ err = fs_init_tx (priv );
706+ if (err )
707+ return err ;
708+
709+ err = fs_init_rx (priv );
710+ if (err )
711+ fs_cleanup_tx (priv );
712+
713+ return err ;
544714}
0 commit comments