8
8
#define IXGBE_IPSEC_KEY_BITS 160
9
9
static const char aes_gcm_name [] = "rfc4106(gcm(aes))" ;
10
10
11
+ static void ixgbe_ipsec_del_sa (struct xfrm_state * xs );
12
+
11
13
/**
12
14
* ixgbe_ipsec_set_tx_sa - set the Tx SA registers
13
15
* @hw: hw specific details
@@ -289,6 +291,13 @@ static void ixgbe_ipsec_start_engine(struct ixgbe_adapter *adapter)
289
291
/**
290
292
* ixgbe_ipsec_restore - restore the ipsec HW settings after a reset
291
293
* @adapter: board private structure
294
+ *
295
+ * Reload the HW tables from the SW tables after they've been bashed
296
+ * by a chip reset.
297
+ *
298
+ * Any VF entries are removed from the SW and HW tables since either
299
+ * (a) the VF also gets reset on PF reset and will ask again for the
300
+ * offloads, or (b) the VF has been removed by a change in the num_vfs.
292
301
**/
293
302
void ixgbe_ipsec_restore (struct ixgbe_adapter * adapter )
294
303
{
@@ -306,16 +315,24 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
306
315
307
316
/* reload the Rx and Tx keys */
308
317
for (i = 0 ; i < IXGBE_IPSEC_MAX_SA_COUNT ; i ++ ) {
309
- struct rx_sa * rsa = & ipsec -> rx_tbl [i ];
310
- struct tx_sa * tsa = & ipsec -> tx_tbl [i ];
311
-
312
- if (rsa -> used )
313
- ixgbe_ipsec_set_rx_sa (hw , i , rsa -> xs -> id .spi ,
314
- rsa -> key , rsa -> salt ,
315
- rsa -> mode , rsa -> iptbl_ind );
318
+ struct rx_sa * r = & ipsec -> rx_tbl [i ];
319
+ struct tx_sa * t = & ipsec -> tx_tbl [i ];
320
+
321
+ if (r -> used ) {
322
+ if (r -> mode & IXGBE_RXTXMOD_VF )
323
+ ixgbe_ipsec_del_sa (r -> xs );
324
+ else
325
+ ixgbe_ipsec_set_rx_sa (hw , i , r -> xs -> id .spi ,
326
+ r -> key , r -> salt ,
327
+ r -> mode , r -> iptbl_ind );
328
+ }
316
329
317
- if (tsa -> used )
318
- ixgbe_ipsec_set_tx_sa (hw , i , tsa -> key , tsa -> salt );
330
+ if (t -> used ) {
331
+ if (t -> mode & IXGBE_RXTXMOD_VF )
332
+ ixgbe_ipsec_del_sa (t -> xs );
333
+ else
334
+ ixgbe_ipsec_set_tx_sa (hw , i , t -> key , t -> salt );
335
+ }
319
336
}
320
337
321
338
/* reload the IP addrs */
@@ -381,6 +398,8 @@ static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
381
398
rcu_read_lock ();
382
399
hash_for_each_possible_rcu (ipsec -> rx_sa_list , rsa , hlist ,
383
400
(__force u32 )spi ) {
401
+ if (rsa -> mode & IXGBE_RXTXMOD_VF )
402
+ continue ;
384
403
if (spi == rsa -> xs -> id .spi &&
385
404
((ip4 && * daddr == rsa -> xs -> id .daddr .a4 ) ||
386
405
(!ip4 && !memcmp (daddr , & rsa -> xs -> id .daddr .a6 ,
@@ -808,6 +827,225 @@ static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
808
827
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok ,
809
828
};
810
829
830
+ /**
831
+ * ixgbe_ipsec_vf_clear - clear the tables of data for a VF
832
+ * @adapter: board private structure
833
+ * @vf: VF id to be removed
834
+ **/
835
+ void ixgbe_ipsec_vf_clear (struct ixgbe_adapter * adapter , u32 vf )
836
+ {
837
+ struct ixgbe_ipsec * ipsec = adapter -> ipsec ;
838
+ int i ;
839
+
840
+ /* search rx sa table */
841
+ for (i = 0 ; i < IXGBE_IPSEC_MAX_SA_COUNT && ipsec -> num_rx_sa ; i ++ ) {
842
+ if (!ipsec -> rx_tbl [i ].used )
843
+ continue ;
844
+ if (ipsec -> rx_tbl [i ].mode & IXGBE_RXTXMOD_VF &&
845
+ ipsec -> rx_tbl [i ].vf == vf )
846
+ ixgbe_ipsec_del_sa (ipsec -> rx_tbl [i ].xs );
847
+ }
848
+
849
+ /* search tx sa table */
850
+ for (i = 0 ; i < IXGBE_IPSEC_MAX_SA_COUNT && ipsec -> num_tx_sa ; i ++ ) {
851
+ if (!ipsec -> tx_tbl [i ].used )
852
+ continue ;
853
+ if (ipsec -> tx_tbl [i ].mode & IXGBE_RXTXMOD_VF &&
854
+ ipsec -> tx_tbl [i ].vf == vf )
855
+ ixgbe_ipsec_del_sa (ipsec -> tx_tbl [i ].xs );
856
+ }
857
+ }
858
+
859
+ /**
860
+ * ixgbe_ipsec_vf_add_sa - translate VF request to SA add
861
+ * @adapter: board private structure
862
+ * @msgbuf: The message buffer
863
+ * @vf: the VF index
864
+ *
865
+ * Make up a new xs and algorithm info from the data sent by the VF.
866
+ * We only need to sketch in just enough to set up the HW offload.
867
+ * Put the resulting offload_handle into the return message to the VF.
868
+ *
869
+ * Returns 0 or error value
870
+ **/
871
+ int ixgbe_ipsec_vf_add_sa (struct ixgbe_adapter * adapter , u32 * msgbuf , u32 vf )
872
+ {
873
+ struct ixgbe_ipsec * ipsec = adapter -> ipsec ;
874
+ struct xfrm_algo_desc * algo ;
875
+ struct sa_mbx_msg * sam ;
876
+ struct xfrm_state * xs ;
877
+ size_t aead_len ;
878
+ u16 sa_idx ;
879
+ u32 pfsa ;
880
+ int err ;
881
+
882
+ sam = (struct sa_mbx_msg * )(& msgbuf [1 ]);
883
+ if (!adapter -> vfinfo [vf ].trusted ) {
884
+ e_warn (drv , "VF %d attempted to add an IPsec SA\n" , vf );
885
+ err = - EACCES ;
886
+ goto err_out ;
887
+ }
888
+
889
+ /* Tx IPsec offload doesn't seem to work on this
890
+ * device, so block these requests for now.
891
+ */
892
+ if (!(sam -> flags & XFRM_OFFLOAD_INBOUND )) {
893
+ err = - ENXIO ;
894
+ goto err_out ;
895
+ }
896
+
897
+ xs = kzalloc (sizeof (* xs ), GFP_KERNEL );
898
+ if (unlikely (!xs )) {
899
+ err = - ENOMEM ;
900
+ goto err_out ;
901
+ }
902
+
903
+ xs -> xso .flags = sam -> flags ;
904
+ xs -> id .spi = sam -> spi ;
905
+ xs -> id .proto = sam -> proto ;
906
+ xs -> props .family = sam -> family ;
907
+ if (xs -> props .family == AF_INET6 )
908
+ memcpy (& xs -> id .daddr .a6 , sam -> addr , sizeof (xs -> id .daddr .a6 ));
909
+ else
910
+ memcpy (& xs -> id .daddr .a4 , sam -> addr , sizeof (xs -> id .daddr .a4 ));
911
+ xs -> xso .dev = adapter -> netdev ;
912
+
913
+ algo = xfrm_aead_get_byname (aes_gcm_name , IXGBE_IPSEC_AUTH_BITS , 1 );
914
+ if (unlikely (!algo )) {
915
+ err = - ENOENT ;
916
+ goto err_xs ;
917
+ }
918
+
919
+ aead_len = sizeof (* xs -> aead ) + IXGBE_IPSEC_KEY_BITS / 8 ;
920
+ xs -> aead = kzalloc (aead_len , GFP_KERNEL );
921
+ if (unlikely (!xs -> aead )) {
922
+ err = - ENOMEM ;
923
+ goto err_xs ;
924
+ }
925
+
926
+ xs -> props .ealgo = algo -> desc .sadb_alg_id ;
927
+ xs -> geniv = algo -> uinfo .aead .geniv ;
928
+ xs -> aead -> alg_icv_len = IXGBE_IPSEC_AUTH_BITS ;
929
+ xs -> aead -> alg_key_len = IXGBE_IPSEC_KEY_BITS ;
930
+ memcpy (xs -> aead -> alg_key , sam -> key , sizeof (sam -> key ));
931
+ memcpy (xs -> aead -> alg_name , aes_gcm_name , sizeof (aes_gcm_name ));
932
+
933
+ /* set up the HW offload */
934
+ err = ixgbe_ipsec_add_sa (xs );
935
+ if (err )
936
+ goto err_aead ;
937
+
938
+ pfsa = xs -> xso .offload_handle ;
939
+ if (pfsa < IXGBE_IPSEC_BASE_TX_INDEX ) {
940
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_RX_INDEX ;
941
+ ipsec -> rx_tbl [sa_idx ].vf = vf ;
942
+ ipsec -> rx_tbl [sa_idx ].mode |= IXGBE_RXTXMOD_VF ;
943
+ } else {
944
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_TX_INDEX ;
945
+ ipsec -> tx_tbl [sa_idx ].vf = vf ;
946
+ ipsec -> tx_tbl [sa_idx ].mode |= IXGBE_RXTXMOD_VF ;
947
+ }
948
+
949
+ msgbuf [1 ] = xs -> xso .offload_handle ;
950
+
951
+ return 0 ;
952
+
953
+ err_aead :
954
+ memset (xs -> aead , 0 , sizeof (* xs -> aead ));
955
+ kfree (xs -> aead );
956
+ err_xs :
957
+ memset (xs , 0 , sizeof (* xs ));
958
+ kfree (xs );
959
+ err_out :
960
+ msgbuf [1 ] = err ;
961
+ return err ;
962
+ }
963
+
964
+ /**
965
+ * ixgbe_ipsec_vf_del_sa - translate VF request to SA delete
966
+ * @adapter: board private structure
967
+ * @msgbuf: The message buffer
968
+ * @vf: the VF index
969
+ *
970
+ * Given the offload_handle sent by the VF, look for the related SA table
971
+ * entry and use its xs field to call for a delete of the SA.
972
+ *
973
+ * Note: We silently ignore requests to delete entries that are already
974
+ * set to unused because when a VF is set to "DOWN", the PF first
975
+ * gets a reset and clears all the VF's entries; then the VF's
976
+ * XFRM stack sends individual deletes for each entry, which the
977
+ * reset already removed. In the future it might be good to try to
978
+ * optimize this so not so many unnecessary delete messages are sent.
979
+ *
980
+ * Returns 0 or error value
981
+ **/
982
+ int ixgbe_ipsec_vf_del_sa (struct ixgbe_adapter * adapter , u32 * msgbuf , u32 vf )
983
+ {
984
+ struct ixgbe_ipsec * ipsec = adapter -> ipsec ;
985
+ struct xfrm_state * xs ;
986
+ u32 pfsa = msgbuf [1 ];
987
+ u16 sa_idx ;
988
+
989
+ if (!adapter -> vfinfo [vf ].trusted ) {
990
+ e_err (drv , "vf %d attempted to delete an SA\n" , vf );
991
+ return - EPERM ;
992
+ }
993
+
994
+ if (pfsa < IXGBE_IPSEC_BASE_TX_INDEX ) {
995
+ struct rx_sa * rsa ;
996
+
997
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_RX_INDEX ;
998
+ if (sa_idx >= IXGBE_IPSEC_MAX_SA_COUNT ) {
999
+ e_err (drv , "vf %d SA index %d out of range\n" ,
1000
+ vf , sa_idx );
1001
+ return - EINVAL ;
1002
+ }
1003
+
1004
+ rsa = & ipsec -> rx_tbl [sa_idx ];
1005
+
1006
+ if (!rsa -> used )
1007
+ return 0 ;
1008
+
1009
+ if (!(rsa -> mode & IXGBE_RXTXMOD_VF ) ||
1010
+ rsa -> vf != vf ) {
1011
+ e_err (drv , "vf %d bad Rx SA index %d\n" , vf , sa_idx );
1012
+ return - ENOENT ;
1013
+ }
1014
+
1015
+ xs = ipsec -> rx_tbl [sa_idx ].xs ;
1016
+ } else {
1017
+ struct tx_sa * tsa ;
1018
+
1019
+ sa_idx = pfsa - IXGBE_IPSEC_BASE_TX_INDEX ;
1020
+ if (sa_idx >= IXGBE_IPSEC_MAX_SA_COUNT ) {
1021
+ e_err (drv , "vf %d SA index %d out of range\n" ,
1022
+ vf , sa_idx );
1023
+ return - EINVAL ;
1024
+ }
1025
+
1026
+ tsa = & ipsec -> tx_tbl [sa_idx ];
1027
+
1028
+ if (!tsa -> used )
1029
+ return 0 ;
1030
+
1031
+ if (!(tsa -> mode & IXGBE_RXTXMOD_VF ) ||
1032
+ tsa -> vf != vf ) {
1033
+ e_err (drv , "vf %d bad Tx SA index %d\n" , vf , sa_idx );
1034
+ return - ENOENT ;
1035
+ }
1036
+
1037
+ xs = ipsec -> tx_tbl [sa_idx ].xs ;
1038
+ }
1039
+
1040
+ ixgbe_ipsec_del_sa (xs );
1041
+
1042
+ /* remove the xs that was made-up in the add request */
1043
+ memset (xs , 0 , sizeof (* xs ));
1044
+ kfree (xs );
1045
+
1046
+ return 0 ;
1047
+ }
1048
+
811
1049
/**
812
1050
* ixgbe_ipsec_tx - setup Tx flags for ipsec offload
813
1051
* @tx_ring: outgoing context
0 commit comments