35
35
#include <crypto/aead.h>
36
36
#include <linux/inetdevice.h>
37
37
#include <linux/netdevice.h>
38
+ #include <net/netevent.h>
38
39
39
40
#include "en.h"
40
41
#include "ipsec.h"
41
42
#include "ipsec_rxtx.h"
42
43
43
44
#define MLX5_IPSEC_RESCHED msecs_to_jiffies(1000)
45
+ #define MLX5E_IPSEC_TUNNEL_SA XA_MARK_1
44
46
45
47
static struct mlx5e_ipsec_sa_entry * to_ipsec_sa_entry (struct xfrm_state * x )
46
48
{
@@ -251,7 +253,7 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
251
253
struct neighbour * n ;
252
254
u8 addr [ETH_ALEN ];
253
255
254
- if (attrs -> mode != XFRM_MODE_TUNNEL &&
256
+ if (attrs -> mode != XFRM_MODE_TUNNEL ||
255
257
attrs -> type != XFRM_DEV_OFFLOAD_PACKET )
256
258
return ;
257
259
@@ -267,6 +269,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
267
269
if (IS_ERR (n ))
268
270
return ;
269
271
neigh_event_send (n , NULL );
272
+ attrs -> drop = true;
273
+ break ;
270
274
}
271
275
neigh_ha_snapshot (addr , n , netdev );
272
276
ether_addr_copy (attrs -> smac , addr );
@@ -279,6 +283,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
279
283
if (IS_ERR (n ))
280
284
return ;
281
285
neigh_event_send (n , NULL );
286
+ attrs -> drop = true;
287
+ break ;
282
288
}
283
289
neigh_ha_snapshot (addr , n , netdev );
284
290
ether_addr_copy (attrs -> dmac , addr );
@@ -507,34 +513,81 @@ static void mlx5e_ipsec_set_esn_ops(struct mlx5e_ipsec_sa_entry *sa_entry)
507
513
sa_entry -> set_iv_op = mlx5e_ipsec_set_iv ;
508
514
}
509
515
516
+ static void mlx5e_ipsec_handle_netdev_event (struct work_struct * _work )
517
+ {
518
+ struct mlx5e_ipsec_work * work =
519
+ container_of (_work , struct mlx5e_ipsec_work , work );
520
+ struct mlx5e_ipsec_sa_entry * sa_entry = work -> sa_entry ;
521
+ struct mlx5e_ipsec_netevent_data * data = work -> data ;
522
+ struct mlx5_accel_esp_xfrm_attrs * attrs ;
523
+
524
+ attrs = & sa_entry -> attrs ;
525
+
526
+ switch (attrs -> dir ) {
527
+ case XFRM_DEV_OFFLOAD_IN :
528
+ ether_addr_copy (attrs -> smac , data -> addr );
529
+ break ;
530
+ case XFRM_DEV_OFFLOAD_OUT :
531
+ ether_addr_copy (attrs -> dmac , data -> addr );
532
+ break ;
533
+ default :
534
+ WARN_ON_ONCE (true);
535
+ }
536
+ attrs -> drop = false;
537
+ mlx5e_accel_ipsec_fs_modify (sa_entry );
538
+ }
539
+
510
540
static int mlx5_ipsec_create_work (struct mlx5e_ipsec_sa_entry * sa_entry )
511
541
{
512
542
struct xfrm_state * x = sa_entry -> x ;
513
543
struct mlx5e_ipsec_work * work ;
544
+ void * data = NULL ;
514
545
515
546
switch (x -> xso .type ) {
516
547
case XFRM_DEV_OFFLOAD_CRYPTO :
517
548
if (!(x -> props .flags & XFRM_STATE_ESN ))
518
549
return 0 ;
519
550
break ;
551
+ case XFRM_DEV_OFFLOAD_PACKET :
552
+ if (x -> props .mode != XFRM_MODE_TUNNEL )
553
+ return 0 ;
554
+ break ;
520
555
default :
521
- return 0 ;
556
+ break ;
522
557
}
523
558
524
559
work = kzalloc (sizeof (* work ), GFP_KERNEL );
525
560
if (!work )
526
561
return - ENOMEM ;
527
562
528
- work -> data = kzalloc (sizeof (* sa_entry ), GFP_KERNEL );
529
- if (!work -> data ) {
530
- kfree (work );
531
- return - ENOMEM ;
563
+ switch (x -> xso .type ) {
564
+ case XFRM_DEV_OFFLOAD_CRYPTO :
565
+ data = kzalloc (sizeof (* sa_entry ), GFP_KERNEL );
566
+ if (!data )
567
+ goto free_work ;
568
+
569
+ INIT_WORK (& work -> work , mlx5e_ipsec_modify_state );
570
+ break ;
571
+ case XFRM_DEV_OFFLOAD_PACKET :
572
+ data = kzalloc (sizeof (struct mlx5e_ipsec_netevent_data ),
573
+ GFP_KERNEL );
574
+ if (!data )
575
+ goto free_work ;
576
+
577
+ INIT_WORK (& work -> work , mlx5e_ipsec_handle_netdev_event );
578
+ break ;
579
+ default :
580
+ break ;
532
581
}
533
582
534
- INIT_WORK ( & work -> work , mlx5e_ipsec_modify_state ) ;
583
+ work -> data = data ;
535
584
work -> sa_entry = sa_entry ;
536
585
sa_entry -> work = work ;
537
586
return 0 ;
587
+
588
+ free_work :
589
+ kfree (work );
590
+ return - ENOMEM ;
538
591
}
539
592
540
593
static int mlx5e_ipsec_create_dwork (struct mlx5e_ipsec_sa_entry * sa_entry )
@@ -629,6 +682,12 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
629
682
if (sa_entry -> dwork )
630
683
queue_delayed_work (ipsec -> wq , & sa_entry -> dwork -> dwork ,
631
684
MLX5_IPSEC_RESCHED );
685
+
686
+ if (x -> xso .type == XFRM_DEV_OFFLOAD_PACKET &&
687
+ x -> props .mode == XFRM_MODE_TUNNEL )
688
+ xa_set_mark (& ipsec -> sadb , sa_entry -> ipsec_obj_id ,
689
+ MLX5E_IPSEC_TUNNEL_SA );
690
+
632
691
out :
633
692
x -> xso .offload_handle = (unsigned long )sa_entry ;
634
693
return 0 ;
@@ -651,6 +710,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
651
710
static void mlx5e_xfrm_del_state (struct xfrm_state * x )
652
711
{
653
712
struct mlx5e_ipsec_sa_entry * sa_entry = to_ipsec_sa_entry (x );
713
+ struct mlx5_accel_esp_xfrm_attrs * attrs = & sa_entry -> attrs ;
654
714
struct mlx5e_ipsec * ipsec = sa_entry -> ipsec ;
655
715
struct mlx5e_ipsec_sa_entry * old ;
656
716
@@ -659,6 +719,12 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
659
719
660
720
old = xa_erase_bh (& ipsec -> sadb , sa_entry -> ipsec_obj_id );
661
721
WARN_ON (old != sa_entry );
722
+
723
+ if (attrs -> mode == XFRM_MODE_TUNNEL &&
724
+ attrs -> type == XFRM_DEV_OFFLOAD_PACKET )
725
+ /* Make sure that no ARP requests are running in parallel */
726
+ flush_workqueue (ipsec -> wq );
727
+
662
728
}
663
729
664
730
static void mlx5e_xfrm_free_state (struct xfrm_state * x )
@@ -683,6 +749,46 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
683
749
kfree (sa_entry );
684
750
}
685
751
752
+ static int mlx5e_ipsec_netevent_event (struct notifier_block * nb ,
753
+ unsigned long event , void * ptr )
754
+ {
755
+ struct mlx5_accel_esp_xfrm_attrs * attrs ;
756
+ struct mlx5e_ipsec_netevent_data * data ;
757
+ struct mlx5e_ipsec_sa_entry * sa_entry ;
758
+ struct mlx5e_ipsec * ipsec ;
759
+ struct neighbour * n = ptr ;
760
+ struct net_device * netdev ;
761
+ struct xfrm_state * x ;
762
+ unsigned long idx ;
763
+
764
+ if (event != NETEVENT_NEIGH_UPDATE || !(n -> nud_state & NUD_VALID ))
765
+ return NOTIFY_DONE ;
766
+
767
+ ipsec = container_of (nb , struct mlx5e_ipsec , netevent_nb );
768
+ xa_for_each_marked (& ipsec -> sadb , idx , sa_entry , MLX5E_IPSEC_TUNNEL_SA ) {
769
+ attrs = & sa_entry -> attrs ;
770
+
771
+ if (attrs -> family == AF_INET ) {
772
+ if (!neigh_key_eq32 (n , & attrs -> saddr .a4 ) &&
773
+ !neigh_key_eq32 (n , & attrs -> daddr .a4 ))
774
+ continue ;
775
+ } else {
776
+ if (!neigh_key_eq128 (n , & attrs -> saddr .a4 ) &&
777
+ !neigh_key_eq128 (n , & attrs -> daddr .a4 ))
778
+ continue ;
779
+ }
780
+
781
+ x = sa_entry -> x ;
782
+ netdev = x -> xso .real_dev ;
783
+ data = sa_entry -> work -> data ;
784
+
785
+ neigh_ha_snapshot (data -> addr , n , netdev );
786
+ queue_work (ipsec -> wq , & sa_entry -> work -> work );
787
+ }
788
+
789
+ return NOTIFY_DONE ;
790
+ }
791
+
686
792
void mlx5e_ipsec_init (struct mlx5e_priv * priv )
687
793
{
688
794
struct mlx5e_ipsec * ipsec ;
@@ -711,6 +817,13 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv)
711
817
goto err_aso ;
712
818
}
713
819
820
+ if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_TUNNEL ) {
821
+ ipsec -> netevent_nb .notifier_call = mlx5e_ipsec_netevent_event ;
822
+ ret = register_netevent_notifier (& ipsec -> netevent_nb );
823
+ if (ret )
824
+ goto clear_aso ;
825
+ }
826
+
714
827
ret = mlx5e_accel_ipsec_fs_init (ipsec );
715
828
if (ret )
716
829
goto err_fs_init ;
@@ -721,6 +834,9 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv)
721
834
return ;
722
835
723
836
err_fs_init :
837
+ if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_TUNNEL )
838
+ unregister_netevent_notifier (& ipsec -> netevent_nb );
839
+ clear_aso :
724
840
if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_PACKET_OFFLOAD )
725
841
mlx5e_ipsec_aso_cleanup (ipsec );
726
842
err_aso :
@@ -739,6 +855,8 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv)
739
855
return ;
740
856
741
857
mlx5e_accel_ipsec_fs_cleanup (ipsec );
858
+ if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_TUNNEL )
859
+ unregister_netevent_notifier (& ipsec -> netevent_nb );
742
860
if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_PACKET_OFFLOAD )
743
861
mlx5e_ipsec_aso_cleanup (ipsec );
744
862
destroy_workqueue (ipsec -> wq );
0 commit comments