Skip to content

Commit eda0333

Browse files
Shannon NelsonJeff Kirsher
authored andcommitted
ixgbe: add VF IPsec management
Add functions to translate VF IPsec offload add and delete requests into something the existing code can work with. Signed-off-by: Shannon Nelson <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 99a7b0c commit eda0333

File tree

2 files changed

+260
-9
lines changed

2 files changed

+260
-9
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.c

Lines changed: 247 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#define IXGBE_IPSEC_KEY_BITS 160
99
static const char aes_gcm_name[] = "rfc4106(gcm(aes))";
1010

11+
static void ixgbe_ipsec_del_sa(struct xfrm_state *xs);
12+
1113
/**
1214
* ixgbe_ipsec_set_tx_sa - set the Tx SA registers
1315
* @hw: hw specific details
@@ -289,6 +291,13 @@ static void ixgbe_ipsec_start_engine(struct ixgbe_adapter *adapter)
289291
/**
290292
* ixgbe_ipsec_restore - restore the ipsec HW settings after a reset
291293
* @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.
292301
**/
293302
void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
294303
{
@@ -306,16 +315,24 @@ void ixgbe_ipsec_restore(struct ixgbe_adapter *adapter)
306315

307316
/* reload the Rx and Tx keys */
308317
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+
}
316329

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+
}
319336
}
320337

321338
/* reload the IP addrs */
@@ -381,6 +398,8 @@ static struct xfrm_state *ixgbe_ipsec_find_rx_state(struct ixgbe_ipsec *ipsec,
381398
rcu_read_lock();
382399
hash_for_each_possible_rcu(ipsec->rx_sa_list, rsa, hlist,
383400
(__force u32)spi) {
401+
if (rsa->mode & IXGBE_RXTXMOD_VF)
402+
continue;
384403
if (spi == rsa->xs->id.spi &&
385404
((ip4 && *daddr == rsa->xs->id.daddr.a4) ||
386405
(!ip4 && !memcmp(daddr, &rsa->xs->id.daddr.a6,
@@ -808,6 +827,225 @@ static const struct xfrmdev_ops ixgbe_xfrmdev_ops = {
808827
.xdo_dev_offload_ok = ixgbe_ipsec_offload_ok,
809828
};
810829

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+
8111049
/**
8121050
* ixgbe_ipsec_tx - setup Tx flags for ipsec offload
8131051
* @tx_ring: outgoing context

drivers/net/ethernet/intel/ixgbe/ixgbe_ipsec.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum ixgbe_ipsec_tbl_sel {
2626
#define IXGBE_RXMOD_PROTO_ESP 0x00000004
2727
#define IXGBE_RXMOD_DECRYPT 0x00000008
2828
#define IXGBE_RXMOD_IPV6 0x00000010
29+
#define IXGBE_RXTXMOD_VF 0x00000020
2930

3031
struct rx_sa {
3132
struct hlist_node hlist;
@@ -37,6 +38,7 @@ struct rx_sa {
3738
u8 iptbl_ind;
3839
bool used;
3940
bool decrypt;
41+
u32 vf;
4042
};
4143

4244
struct rx_ip_sa {
@@ -49,8 +51,10 @@ struct tx_sa {
4951
struct xfrm_state *xs;
5052
u32 key[4];
5153
u32 salt;
54+
u32 mode;
5255
bool encrypt;
5356
bool used;
57+
u32 vf;
5458
};
5559

5660
struct ixgbe_ipsec_tx_data {
@@ -67,4 +71,13 @@ struct ixgbe_ipsec {
6771
struct tx_sa *tx_tbl;
6872
DECLARE_HASHTABLE(rx_sa_list, 10);
6973
};
74+
75+
struct sa_mbx_msg {
76+
__be32 spi;
77+
u8 flags;
78+
u8 proto;
79+
u16 family;
80+
__be32 addr[4];
81+
u32 key[5];
82+
};
7083
#endif /* _IXGBE_IPSEC_H_ */

0 commit comments

Comments
 (0)