3535#include <crypto/aead.h>
3636#include <linux/inetdevice.h>
3737#include <linux/netdevice.h>
38+ #include <net/netevent.h>
3839
3940#include "en.h"
4041#include "ipsec.h"
4142#include "ipsec_rxtx.h"
4243
4344#define MLX5_IPSEC_RESCHED msecs_to_jiffies(1000)
45+ #define MLX5E_IPSEC_TUNNEL_SA XA_MARK_1
4446
4547static struct mlx5e_ipsec_sa_entry * to_ipsec_sa_entry (struct xfrm_state * x )
4648{
@@ -251,7 +253,7 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
251253 struct neighbour * n ;
252254 u8 addr [ETH_ALEN ];
253255
254- if (attrs -> mode != XFRM_MODE_TUNNEL &&
256+ if (attrs -> mode != XFRM_MODE_TUNNEL ||
255257 attrs -> type != XFRM_DEV_OFFLOAD_PACKET )
256258 return ;
257259
@@ -267,6 +269,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
267269 if (IS_ERR (n ))
268270 return ;
269271 neigh_event_send (n , NULL );
272+ attrs -> drop = true;
273+ break ;
270274 }
271275 neigh_ha_snapshot (addr , n , netdev );
272276 ether_addr_copy (attrs -> smac , addr );
@@ -279,6 +283,8 @@ static void mlx5e_ipsec_init_macs(struct mlx5e_ipsec_sa_entry *sa_entry,
279283 if (IS_ERR (n ))
280284 return ;
281285 neigh_event_send (n , NULL );
286+ attrs -> drop = true;
287+ break ;
282288 }
283289 neigh_ha_snapshot (addr , n , netdev );
284290 ether_addr_copy (attrs -> dmac , addr );
@@ -507,34 +513,81 @@ static void mlx5e_ipsec_set_esn_ops(struct mlx5e_ipsec_sa_entry *sa_entry)
507513 sa_entry -> set_iv_op = mlx5e_ipsec_set_iv ;
508514}
509515
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+
510540static int mlx5_ipsec_create_work (struct mlx5e_ipsec_sa_entry * sa_entry )
511541{
512542 struct xfrm_state * x = sa_entry -> x ;
513543 struct mlx5e_ipsec_work * work ;
544+ void * data = NULL ;
514545
515546 switch (x -> xso .type ) {
516547 case XFRM_DEV_OFFLOAD_CRYPTO :
517548 if (!(x -> props .flags & XFRM_STATE_ESN ))
518549 return 0 ;
519550 break ;
551+ case XFRM_DEV_OFFLOAD_PACKET :
552+ if (x -> props .mode != XFRM_MODE_TUNNEL )
553+ return 0 ;
554+ break ;
520555 default :
521- return 0 ;
556+ break ;
522557 }
523558
524559 work = kzalloc (sizeof (* work ), GFP_KERNEL );
525560 if (!work )
526561 return - ENOMEM ;
527562
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 ;
532581 }
533582
534- INIT_WORK ( & work -> work , mlx5e_ipsec_modify_state ) ;
583+ work -> data = data ;
535584 work -> sa_entry = sa_entry ;
536585 sa_entry -> work = work ;
537586 return 0 ;
587+
588+ free_work :
589+ kfree (work );
590+ return - ENOMEM ;
538591}
539592
540593static 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,
629682 if (sa_entry -> dwork )
630683 queue_delayed_work (ipsec -> wq , & sa_entry -> dwork -> dwork ,
631684 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+
632691out :
633692 x -> xso .offload_handle = (unsigned long )sa_entry ;
634693 return 0 ;
@@ -651,6 +710,7 @@ static int mlx5e_xfrm_add_state(struct xfrm_state *x,
651710static void mlx5e_xfrm_del_state (struct xfrm_state * x )
652711{
653712 struct mlx5e_ipsec_sa_entry * sa_entry = to_ipsec_sa_entry (x );
713+ struct mlx5_accel_esp_xfrm_attrs * attrs = & sa_entry -> attrs ;
654714 struct mlx5e_ipsec * ipsec = sa_entry -> ipsec ;
655715 struct mlx5e_ipsec_sa_entry * old ;
656716
@@ -659,6 +719,12 @@ static void mlx5e_xfrm_del_state(struct xfrm_state *x)
659719
660720 old = xa_erase_bh (& ipsec -> sadb , sa_entry -> ipsec_obj_id );
661721 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+
662728}
663729
664730static void mlx5e_xfrm_free_state (struct xfrm_state * x )
@@ -683,6 +749,46 @@ static void mlx5e_xfrm_free_state(struct xfrm_state *x)
683749 kfree (sa_entry );
684750}
685751
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+
686792void mlx5e_ipsec_init (struct mlx5e_priv * priv )
687793{
688794 struct mlx5e_ipsec * ipsec ;
@@ -711,6 +817,13 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv)
711817 goto err_aso ;
712818 }
713819
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+
714827 ret = mlx5e_accel_ipsec_fs_init (ipsec );
715828 if (ret )
716829 goto err_fs_init ;
@@ -721,6 +834,9 @@ void mlx5e_ipsec_init(struct mlx5e_priv *priv)
721834 return ;
722835
723836err_fs_init :
837+ if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_TUNNEL )
838+ unregister_netevent_notifier (& ipsec -> netevent_nb );
839+ clear_aso :
724840 if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_PACKET_OFFLOAD )
725841 mlx5e_ipsec_aso_cleanup (ipsec );
726842err_aso :
@@ -739,6 +855,8 @@ void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv)
739855 return ;
740856
741857 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 );
742860 if (mlx5_ipsec_device_caps (priv -> mdev ) & MLX5_IPSEC_CAP_PACKET_OFFLOAD )
743861 mlx5e_ipsec_aso_cleanup (ipsec );
744862 destroy_workqueue (ipsec -> wq );
0 commit comments