1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* Copyright(c) 2018 Oracle and/or its affiliates. All rights reserved. */ |
3 | |
4 | #include "ixgbevf.h" |
5 | #include <net/xfrm.h> |
6 | #include <crypto/aead.h> |
7 | |
8 | #define IXGBE_IPSEC_KEY_BITS 160 |
9 | static const char aes_gcm_name[] = "rfc4106(gcm(aes))" ; |
10 | |
11 | /** |
12 | * ixgbevf_ipsec_set_pf_sa - ask the PF to set up an SA |
13 | * @adapter: board private structure |
14 | * @xs: xfrm info to be sent to the PF |
15 | * |
16 | * Returns: positive offload handle from the PF, or negative error code |
17 | **/ |
18 | static int ixgbevf_ipsec_set_pf_sa(struct ixgbevf_adapter *adapter, |
19 | struct xfrm_state *xs) |
20 | { |
21 | u32 msgbuf[IXGBE_VFMAILBOX_SIZE] = { 0 }; |
22 | struct ixgbe_hw *hw = &adapter->hw; |
23 | struct sa_mbx_msg *sam; |
24 | int ret; |
25 | |
26 | /* send the important bits to the PF */ |
27 | sam = (struct sa_mbx_msg *)(&msgbuf[1]); |
28 | sam->dir = xs->xso.dir; |
29 | sam->spi = xs->id.spi; |
30 | sam->proto = xs->id.proto; |
31 | sam->family = xs->props.family; |
32 | |
33 | if (xs->props.family == AF_INET6) |
34 | memcpy(sam->addr, &xs->id.daddr.a6, sizeof(xs->id.daddr.a6)); |
35 | else |
36 | memcpy(sam->addr, &xs->id.daddr.a4, sizeof(xs->id.daddr.a4)); |
37 | memcpy(sam->key, xs->aead->alg_key, sizeof(sam->key)); |
38 | |
39 | msgbuf[0] = IXGBE_VF_IPSEC_ADD; |
40 | |
41 | spin_lock_bh(lock: &adapter->mbx_lock); |
42 | |
43 | ret = ixgbevf_write_mbx(hw, msg: msgbuf, IXGBE_VFMAILBOX_SIZE); |
44 | if (ret) |
45 | goto out; |
46 | |
47 | ret = ixgbevf_poll_mbx(hw, msg: msgbuf, size: 2); |
48 | if (ret) |
49 | goto out; |
50 | |
51 | ret = (int)msgbuf[1]; |
52 | if (msgbuf[0] & IXGBE_VT_MSGTYPE_FAILURE && ret >= 0) |
53 | ret = -1; |
54 | |
55 | out: |
56 | spin_unlock_bh(lock: &adapter->mbx_lock); |
57 | |
58 | return ret; |
59 | } |
60 | |
61 | /** |
62 | * ixgbevf_ipsec_del_pf_sa - ask the PF to delete an SA |
63 | * @adapter: board private structure |
64 | * @pfsa: sa index returned from PF when created, -1 for all |
65 | * |
66 | * Returns: 0 on success, or negative error code |
67 | **/ |
68 | static int ixgbevf_ipsec_del_pf_sa(struct ixgbevf_adapter *adapter, int pfsa) |
69 | { |
70 | struct ixgbe_hw *hw = &adapter->hw; |
71 | u32 msgbuf[2]; |
72 | int err; |
73 | |
74 | memset(msgbuf, 0, sizeof(msgbuf)); |
75 | msgbuf[0] = IXGBE_VF_IPSEC_DEL; |
76 | msgbuf[1] = (u32)pfsa; |
77 | |
78 | spin_lock_bh(lock: &adapter->mbx_lock); |
79 | |
80 | err = ixgbevf_write_mbx(hw, msg: msgbuf, size: 2); |
81 | if (err) |
82 | goto out; |
83 | |
84 | err = ixgbevf_poll_mbx(hw, msg: msgbuf, size: 2); |
85 | if (err) |
86 | goto out; |
87 | |
88 | out: |
89 | spin_unlock_bh(lock: &adapter->mbx_lock); |
90 | return err; |
91 | } |
92 | |
93 | /** |
94 | * ixgbevf_ipsec_restore - restore the IPsec HW settings after a reset |
95 | * @adapter: board private structure |
96 | * |
97 | * Reload the HW tables from the SW tables after they've been bashed |
98 | * by a chip reset. While we're here, make sure any stale VF data is |
99 | * removed, since we go through reset when num_vfs changes. |
100 | **/ |
101 | void ixgbevf_ipsec_restore(struct ixgbevf_adapter *adapter) |
102 | { |
103 | struct ixgbevf_ipsec *ipsec = adapter->ipsec; |
104 | struct net_device *netdev = adapter->netdev; |
105 | int i; |
106 | |
107 | if (!(adapter->netdev->features & NETIF_F_HW_ESP)) |
108 | return; |
109 | |
110 | /* reload the Rx and Tx keys */ |
111 | for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { |
112 | struct rx_sa *r = &ipsec->rx_tbl[i]; |
113 | struct tx_sa *t = &ipsec->tx_tbl[i]; |
114 | int ret; |
115 | |
116 | if (r->used) { |
117 | ret = ixgbevf_ipsec_set_pf_sa(adapter, xs: r->xs); |
118 | if (ret < 0) |
119 | netdev_err(dev: netdev, format: "reload rx_tbl[%d] failed = %d\n" , |
120 | i, ret); |
121 | } |
122 | |
123 | if (t->used) { |
124 | ret = ixgbevf_ipsec_set_pf_sa(adapter, xs: t->xs); |
125 | if (ret < 0) |
126 | netdev_err(dev: netdev, format: "reload tx_tbl[%d] failed = %d\n" , |
127 | i, ret); |
128 | } |
129 | } |
130 | } |
131 | |
132 | /** |
133 | * ixgbevf_ipsec_find_empty_idx - find the first unused security parameter index |
134 | * @ipsec: pointer to IPsec struct |
135 | * @rxtable: true if we need to look in the Rx table |
136 | * |
137 | * Returns the first unused index in either the Rx or Tx SA table |
138 | **/ |
139 | static |
140 | int ixgbevf_ipsec_find_empty_idx(struct ixgbevf_ipsec *ipsec, bool rxtable) |
141 | { |
142 | u32 i; |
143 | |
144 | if (rxtable) { |
145 | if (ipsec->num_rx_sa == IXGBE_IPSEC_MAX_SA_COUNT) |
146 | return -ENOSPC; |
147 | |
148 | /* search rx sa table */ |
149 | for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { |
150 | if (!ipsec->rx_tbl[i].used) |
151 | return i; |
152 | } |
153 | } else { |
154 | if (ipsec->num_tx_sa == IXGBE_IPSEC_MAX_SA_COUNT) |
155 | return -ENOSPC; |
156 | |
157 | /* search tx sa table */ |
158 | for (i = 0; i < IXGBE_IPSEC_MAX_SA_COUNT; i++) { |
159 | if (!ipsec->tx_tbl[i].used) |
160 | return i; |
161 | } |
162 | } |
163 | |
164 | return -ENOSPC; |
165 | } |
166 | |
167 | /** |
168 | * ixgbevf_ipsec_find_rx_state - find the state that matches |
169 | * @ipsec: pointer to IPsec struct |
170 | * @daddr: inbound address to match |
171 | * @proto: protocol to match |
172 | * @spi: SPI to match |
173 | * @ip4: true if using an IPv4 address |
174 | * |
175 | * Returns a pointer to the matching SA state information |
176 | **/ |
177 | static |
178 | struct xfrm_state *ixgbevf_ipsec_find_rx_state(struct ixgbevf_ipsec *ipsec, |
179 | __be32 *daddr, u8 proto, |
180 | __be32 spi, bool ip4) |
181 | { |
182 | struct xfrm_state *ret = NULL; |
183 | struct rx_sa *rsa; |
184 | |
185 | rcu_read_lock(); |
186 | hash_for_each_possible_rcu(ipsec->rx_sa_list, rsa, hlist, |
187 | (__force u32)spi) { |
188 | if (spi == rsa->xs->id.spi && |
189 | ((ip4 && *daddr == rsa->xs->id.daddr.a4) || |
190 | (!ip4 && !memcmp(p: daddr, q: &rsa->xs->id.daddr.a6, |
191 | size: sizeof(rsa->xs->id.daddr.a6)))) && |
192 | proto == rsa->xs->id.proto) { |
193 | ret = rsa->xs; |
194 | xfrm_state_hold(x: ret); |
195 | break; |
196 | } |
197 | } |
198 | rcu_read_unlock(); |
199 | return ret; |
200 | } |
201 | |
202 | /** |
203 | * ixgbevf_ipsec_parse_proto_keys - find the key and salt based on the protocol |
204 | * @xs: pointer to xfrm_state struct |
205 | * @mykey: pointer to key array to populate |
206 | * @mysalt: pointer to salt value to populate |
207 | * |
208 | * This copies the protocol keys and salt to our own data tables. The |
209 | * 82599 family only supports the one algorithm. |
210 | **/ |
211 | static int ixgbevf_ipsec_parse_proto_keys(struct xfrm_state *xs, |
212 | u32 *mykey, u32 *mysalt) |
213 | { |
214 | struct net_device *dev = xs->xso.real_dev; |
215 | unsigned char *key_data; |
216 | char *alg_name = NULL; |
217 | int key_len; |
218 | |
219 | if (!xs->aead) { |
220 | netdev_err(dev, format: "Unsupported IPsec algorithm\n" ); |
221 | return -EINVAL; |
222 | } |
223 | |
224 | if (xs->aead->alg_icv_len != IXGBE_IPSEC_AUTH_BITS) { |
225 | netdev_err(dev, format: "IPsec offload requires %d bit authentication\n" , |
226 | IXGBE_IPSEC_AUTH_BITS); |
227 | return -EINVAL; |
228 | } |
229 | |
230 | key_data = &xs->aead->alg_key[0]; |
231 | key_len = xs->aead->alg_key_len; |
232 | alg_name = xs->aead->alg_name; |
233 | |
234 | if (strcmp(alg_name, aes_gcm_name)) { |
235 | netdev_err(dev, format: "Unsupported IPsec algorithm - please use %s\n" , |
236 | aes_gcm_name); |
237 | return -EINVAL; |
238 | } |
239 | |
240 | /* The key bytes come down in a big endian array of bytes, so |
241 | * we don't need to do any byte swapping. |
242 | * 160 accounts for 16 byte key and 4 byte salt |
243 | */ |
244 | if (key_len > IXGBE_IPSEC_KEY_BITS) { |
245 | *mysalt = ((u32 *)key_data)[4]; |
246 | } else if (key_len == IXGBE_IPSEC_KEY_BITS) { |
247 | *mysalt = 0; |
248 | } else { |
249 | netdev_err(dev, format: "IPsec hw offload only supports keys up to 128 bits with a 32 bit salt\n" ); |
250 | return -EINVAL; |
251 | } |
252 | memcpy(mykey, key_data, 16); |
253 | |
254 | return 0; |
255 | } |
256 | |
257 | /** |
258 | * ixgbevf_ipsec_add_sa - program device with a security association |
259 | * @xs: pointer to transformer state struct |
260 | * @extack: extack point to fill failure reason |
261 | **/ |
262 | static int ixgbevf_ipsec_add_sa(struct xfrm_state *xs, |
263 | struct netlink_ext_ack *extack) |
264 | { |
265 | struct net_device *dev = xs->xso.real_dev; |
266 | struct ixgbevf_adapter *adapter; |
267 | struct ixgbevf_ipsec *ipsec; |
268 | u16 sa_idx; |
269 | int ret; |
270 | |
271 | adapter = netdev_priv(dev); |
272 | ipsec = adapter->ipsec; |
273 | |
274 | if (xs->id.proto != IPPROTO_ESP && xs->id.proto != IPPROTO_AH) { |
275 | NL_SET_ERR_MSG_MOD(extack, "Unsupported protocol for IPsec offload" ); |
276 | return -EINVAL; |
277 | } |
278 | |
279 | if (xs->props.mode != XFRM_MODE_TRANSPORT) { |
280 | NL_SET_ERR_MSG_MOD(extack, "Unsupported mode for ipsec offload" ); |
281 | return -EINVAL; |
282 | } |
283 | |
284 | if (xs->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) { |
285 | NL_SET_ERR_MSG_MOD(extack, "Unsupported ipsec offload type" ); |
286 | return -EINVAL; |
287 | } |
288 | |
289 | if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { |
290 | struct rx_sa rsa; |
291 | |
292 | if (xs->calg) { |
293 | NL_SET_ERR_MSG_MOD(extack, "Compression offload not supported" ); |
294 | return -EINVAL; |
295 | } |
296 | |
297 | /* find the first unused index */ |
298 | ret = ixgbevf_ipsec_find_empty_idx(ipsec, rxtable: true); |
299 | if (ret < 0) { |
300 | NL_SET_ERR_MSG_MOD(extack, "No space for SA in Rx table!" ); |
301 | return ret; |
302 | } |
303 | sa_idx = (u16)ret; |
304 | |
305 | memset(&rsa, 0, sizeof(rsa)); |
306 | rsa.used = true; |
307 | rsa.xs = xs; |
308 | |
309 | if (rsa.xs->id.proto & IPPROTO_ESP) |
310 | rsa.decrypt = xs->ealg || xs->aead; |
311 | |
312 | /* get the key and salt */ |
313 | ret = ixgbevf_ipsec_parse_proto_keys(xs, mykey: rsa.key, mysalt: &rsa.salt); |
314 | if (ret) { |
315 | NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Rx SA table" ); |
316 | return ret; |
317 | } |
318 | |
319 | /* get ip for rx sa table */ |
320 | if (xs->props.family == AF_INET6) |
321 | memcpy(rsa.ipaddr, &xs->id.daddr.a6, 16); |
322 | else |
323 | memcpy(&rsa.ipaddr[3], &xs->id.daddr.a4, 4); |
324 | |
325 | rsa.mode = IXGBE_RXMOD_VALID; |
326 | if (rsa.xs->id.proto & IPPROTO_ESP) |
327 | rsa.mode |= IXGBE_RXMOD_PROTO_ESP; |
328 | if (rsa.decrypt) |
329 | rsa.mode |= IXGBE_RXMOD_DECRYPT; |
330 | if (rsa.xs->props.family == AF_INET6) |
331 | rsa.mode |= IXGBE_RXMOD_IPV6; |
332 | |
333 | ret = ixgbevf_ipsec_set_pf_sa(adapter, xs); |
334 | if (ret < 0) |
335 | return ret; |
336 | rsa.pfsa = ret; |
337 | |
338 | /* the preparations worked, so save the info */ |
339 | memcpy(&ipsec->rx_tbl[sa_idx], &rsa, sizeof(rsa)); |
340 | |
341 | xs->xso.offload_handle = sa_idx + IXGBE_IPSEC_BASE_RX_INDEX; |
342 | |
343 | ipsec->num_rx_sa++; |
344 | |
345 | /* hash the new entry for faster search in Rx path */ |
346 | hash_add_rcu(ipsec->rx_sa_list, &ipsec->rx_tbl[sa_idx].hlist, |
347 | (__force u32)rsa.xs->id.spi); |
348 | } else { |
349 | struct tx_sa tsa; |
350 | |
351 | /* find the first unused index */ |
352 | ret = ixgbevf_ipsec_find_empty_idx(ipsec, rxtable: false); |
353 | if (ret < 0) { |
354 | NL_SET_ERR_MSG_MOD(extack, "No space for SA in Tx table" ); |
355 | return ret; |
356 | } |
357 | sa_idx = (u16)ret; |
358 | |
359 | memset(&tsa, 0, sizeof(tsa)); |
360 | tsa.used = true; |
361 | tsa.xs = xs; |
362 | |
363 | if (xs->id.proto & IPPROTO_ESP) |
364 | tsa.encrypt = xs->ealg || xs->aead; |
365 | |
366 | ret = ixgbevf_ipsec_parse_proto_keys(xs, mykey: tsa.key, mysalt: &tsa.salt); |
367 | if (ret) { |
368 | NL_SET_ERR_MSG_MOD(extack, "Failed to get key data for Tx SA table" ); |
369 | memset(&tsa, 0, sizeof(tsa)); |
370 | return ret; |
371 | } |
372 | |
373 | ret = ixgbevf_ipsec_set_pf_sa(adapter, xs); |
374 | if (ret < 0) |
375 | return ret; |
376 | tsa.pfsa = ret; |
377 | |
378 | /* the preparations worked, so save the info */ |
379 | memcpy(&ipsec->tx_tbl[sa_idx], &tsa, sizeof(tsa)); |
380 | |
381 | xs->xso.offload_handle = sa_idx + IXGBE_IPSEC_BASE_TX_INDEX; |
382 | |
383 | ipsec->num_tx_sa++; |
384 | } |
385 | |
386 | return 0; |
387 | } |
388 | |
389 | /** |
390 | * ixgbevf_ipsec_del_sa - clear out this specific SA |
391 | * @xs: pointer to transformer state struct |
392 | **/ |
393 | static void ixgbevf_ipsec_del_sa(struct xfrm_state *xs) |
394 | { |
395 | struct net_device *dev = xs->xso.real_dev; |
396 | struct ixgbevf_adapter *adapter; |
397 | struct ixgbevf_ipsec *ipsec; |
398 | u16 sa_idx; |
399 | |
400 | adapter = netdev_priv(dev); |
401 | ipsec = adapter->ipsec; |
402 | |
403 | if (xs->xso.dir == XFRM_DEV_OFFLOAD_IN) { |
404 | sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_RX_INDEX; |
405 | |
406 | if (!ipsec->rx_tbl[sa_idx].used) { |
407 | netdev_err(dev, format: "Invalid Rx SA selected sa_idx=%d offload_handle=%lu\n" , |
408 | sa_idx, xs->xso.offload_handle); |
409 | return; |
410 | } |
411 | |
412 | ixgbevf_ipsec_del_pf_sa(adapter, pfsa: ipsec->rx_tbl[sa_idx].pfsa); |
413 | hash_del_rcu(node: &ipsec->rx_tbl[sa_idx].hlist); |
414 | memset(&ipsec->rx_tbl[sa_idx], 0, sizeof(struct rx_sa)); |
415 | ipsec->num_rx_sa--; |
416 | } else { |
417 | sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX; |
418 | |
419 | if (!ipsec->tx_tbl[sa_idx].used) { |
420 | netdev_err(dev, format: "Invalid Tx SA selected sa_idx=%d offload_handle=%lu\n" , |
421 | sa_idx, xs->xso.offload_handle); |
422 | return; |
423 | } |
424 | |
425 | ixgbevf_ipsec_del_pf_sa(adapter, pfsa: ipsec->tx_tbl[sa_idx].pfsa); |
426 | memset(&ipsec->tx_tbl[sa_idx], 0, sizeof(struct tx_sa)); |
427 | ipsec->num_tx_sa--; |
428 | } |
429 | } |
430 | |
431 | /** |
432 | * ixgbevf_ipsec_offload_ok - can this packet use the xfrm hw offload |
433 | * @skb: current data packet |
434 | * @xs: pointer to transformer state struct |
435 | **/ |
436 | static bool ixgbevf_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) |
437 | { |
438 | if (xs->props.family == AF_INET) { |
439 | /* Offload with IPv4 options is not supported yet */ |
440 | if (ip_hdr(skb)->ihl != 5) |
441 | return false; |
442 | } else { |
443 | /* Offload with IPv6 extension headers is not support yet */ |
444 | if (ipv6_ext_hdr(nexthdr: ipv6_hdr(skb)->nexthdr)) |
445 | return false; |
446 | } |
447 | |
448 | return true; |
449 | } |
450 | |
451 | static const struct xfrmdev_ops ixgbevf_xfrmdev_ops = { |
452 | .xdo_dev_state_add = ixgbevf_ipsec_add_sa, |
453 | .xdo_dev_state_delete = ixgbevf_ipsec_del_sa, |
454 | .xdo_dev_offload_ok = ixgbevf_ipsec_offload_ok, |
455 | }; |
456 | |
457 | /** |
458 | * ixgbevf_ipsec_tx - setup Tx flags for IPsec offload |
459 | * @tx_ring: outgoing context |
460 | * @first: current data packet |
461 | * @itd: ipsec Tx data for later use in building context descriptor |
462 | **/ |
463 | int ixgbevf_ipsec_tx(struct ixgbevf_ring *tx_ring, |
464 | struct ixgbevf_tx_buffer *first, |
465 | struct ixgbevf_ipsec_tx_data *itd) |
466 | { |
467 | struct ixgbevf_adapter *adapter = netdev_priv(dev: tx_ring->netdev); |
468 | struct ixgbevf_ipsec *ipsec = adapter->ipsec; |
469 | struct xfrm_state *xs; |
470 | struct sec_path *sp; |
471 | struct tx_sa *tsa; |
472 | u16 sa_idx; |
473 | |
474 | sp = skb_sec_path(skb: first->skb); |
475 | if (unlikely(!sp->len)) { |
476 | netdev_err(dev: tx_ring->netdev, format: "%s: no xfrm state len = %d\n" , |
477 | __func__, sp->len); |
478 | return 0; |
479 | } |
480 | |
481 | xs = xfrm_input_state(skb: first->skb); |
482 | if (unlikely(!xs)) { |
483 | netdev_err(dev: tx_ring->netdev, format: "%s: no xfrm_input_state() xs = %p\n" , |
484 | __func__, xs); |
485 | return 0; |
486 | } |
487 | |
488 | sa_idx = xs->xso.offload_handle - IXGBE_IPSEC_BASE_TX_INDEX; |
489 | if (unlikely(sa_idx >= IXGBE_IPSEC_MAX_SA_COUNT)) { |
490 | netdev_err(dev: tx_ring->netdev, format: "%s: bad sa_idx=%d handle=%lu\n" , |
491 | __func__, sa_idx, xs->xso.offload_handle); |
492 | return 0; |
493 | } |
494 | |
495 | tsa = &ipsec->tx_tbl[sa_idx]; |
496 | if (unlikely(!tsa->used)) { |
497 | netdev_err(dev: tx_ring->netdev, format: "%s: unused sa_idx=%d\n" , |
498 | __func__, sa_idx); |
499 | return 0; |
500 | } |
501 | |
502 | itd->pfsa = tsa->pfsa - IXGBE_IPSEC_BASE_TX_INDEX; |
503 | |
504 | first->tx_flags |= IXGBE_TX_FLAGS_IPSEC | IXGBE_TX_FLAGS_CSUM; |
505 | |
506 | if (xs->id.proto == IPPROTO_ESP) { |
507 | itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_TYPE_ESP | |
508 | IXGBE_ADVTXD_TUCMD_L4T_TCP; |
509 | if (first->protocol == htons(ETH_P_IP)) |
510 | itd->flags |= IXGBE_ADVTXD_TUCMD_IPV4; |
511 | |
512 | /* The actual trailer length is authlen (16 bytes) plus |
513 | * 2 bytes for the proto and the padlen values, plus |
514 | * padlen bytes of padding. This ends up not the same |
515 | * as the static value found in xs->props.trailer_len (21). |
516 | * |
517 | * ... but if we're doing GSO, don't bother as the stack |
518 | * doesn't add a trailer for those. |
519 | */ |
520 | if (!skb_is_gso(skb: first->skb)) { |
521 | /* The "correct" way to get the auth length would be |
522 | * to use |
523 | * authlen = crypto_aead_authsize(xs->data); |
524 | * but since we know we only have one size to worry |
525 | * about * we can let the compiler use the constant |
526 | * and save us a few CPU cycles. |
527 | */ |
528 | const int authlen = IXGBE_IPSEC_AUTH_BITS / 8; |
529 | struct sk_buff *skb = first->skb; |
530 | u8 padlen; |
531 | int ret; |
532 | |
533 | ret = skb_copy_bits(skb, offset: skb->len - (authlen + 2), |
534 | to: &padlen, len: 1); |
535 | if (unlikely(ret)) |
536 | return 0; |
537 | itd->trailer_len = authlen + 2 + padlen; |
538 | } |
539 | } |
540 | if (tsa->encrypt) |
541 | itd->flags |= IXGBE_ADVTXD_TUCMD_IPSEC_ENCRYPT_EN; |
542 | |
543 | return 1; |
544 | } |
545 | |
546 | /** |
547 | * ixgbevf_ipsec_rx - decode IPsec bits from Rx descriptor |
548 | * @rx_ring: receiving ring |
549 | * @rx_desc: receive data descriptor |
550 | * @skb: current data packet |
551 | * |
552 | * Determine if there was an IPsec encapsulation noticed, and if so set up |
553 | * the resulting status for later in the receive stack. |
554 | **/ |
555 | void ixgbevf_ipsec_rx(struct ixgbevf_ring *rx_ring, |
556 | union ixgbe_adv_rx_desc *rx_desc, |
557 | struct sk_buff *skb) |
558 | { |
559 | struct ixgbevf_adapter *adapter = netdev_priv(dev: rx_ring->netdev); |
560 | __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; |
561 | __le16 ipsec_pkt_types = cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_AH | |
562 | IXGBE_RXDADV_PKTTYPE_IPSEC_ESP); |
563 | struct ixgbevf_ipsec *ipsec = adapter->ipsec; |
564 | struct xfrm_offload *xo = NULL; |
565 | struct xfrm_state *xs = NULL; |
566 | struct ipv6hdr *ip6 = NULL; |
567 | struct iphdr *ip4 = NULL; |
568 | struct sec_path *sp; |
569 | void *daddr; |
570 | __be32 spi; |
571 | u8 *c_hdr; |
572 | u8 proto; |
573 | |
574 | /* Find the IP and crypto headers in the data. |
575 | * We can assume no VLAN header in the way, b/c the |
576 | * hw won't recognize the IPsec packet and anyway the |
577 | * currently VLAN device doesn't support xfrm offload. |
578 | */ |
579 | if (pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPV4)) { |
580 | ip4 = (struct iphdr *)(skb->data + ETH_HLEN); |
581 | daddr = &ip4->daddr; |
582 | c_hdr = (u8 *)ip4 + ip4->ihl * 4; |
583 | } else if (pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPV6)) { |
584 | ip6 = (struct ipv6hdr *)(skb->data + ETH_HLEN); |
585 | daddr = &ip6->daddr; |
586 | c_hdr = (u8 *)ip6 + sizeof(struct ipv6hdr); |
587 | } else { |
588 | return; |
589 | } |
590 | |
591 | switch (pkt_info & ipsec_pkt_types) { |
592 | case cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_AH): |
593 | spi = ((struct ip_auth_hdr *)c_hdr)->spi; |
594 | proto = IPPROTO_AH; |
595 | break; |
596 | case cpu_to_le16(IXGBE_RXDADV_PKTTYPE_IPSEC_ESP): |
597 | spi = ((struct ip_esp_hdr *)c_hdr)->spi; |
598 | proto = IPPROTO_ESP; |
599 | break; |
600 | default: |
601 | return; |
602 | } |
603 | |
604 | xs = ixgbevf_ipsec_find_rx_state(ipsec, daddr, proto, spi, ip4: !!ip4); |
605 | if (unlikely(!xs)) |
606 | return; |
607 | |
608 | sp = secpath_set(skb); |
609 | if (unlikely(!sp)) |
610 | return; |
611 | |
612 | sp->xvec[sp->len++] = xs; |
613 | sp->olen++; |
614 | xo = xfrm_offload(skb); |
615 | xo->flags = CRYPTO_DONE; |
616 | xo->status = CRYPTO_SUCCESS; |
617 | |
618 | adapter->rx_ipsec++; |
619 | } |
620 | |
621 | /** |
622 | * ixgbevf_init_ipsec_offload - initialize registers for IPsec operation |
623 | * @adapter: board private structure |
624 | **/ |
625 | void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter) |
626 | { |
627 | struct ixgbevf_ipsec *ipsec; |
628 | size_t size; |
629 | |
630 | switch (adapter->hw.api_version) { |
631 | case ixgbe_mbox_api_14: |
632 | case ixgbe_mbox_api_15: |
633 | break; |
634 | default: |
635 | return; |
636 | } |
637 | |
638 | ipsec = kzalloc(size: sizeof(*ipsec), GFP_KERNEL); |
639 | if (!ipsec) |
640 | goto err1; |
641 | hash_init(ipsec->rx_sa_list); |
642 | |
643 | size = sizeof(struct rx_sa) * IXGBE_IPSEC_MAX_SA_COUNT; |
644 | ipsec->rx_tbl = kzalloc(size, GFP_KERNEL); |
645 | if (!ipsec->rx_tbl) |
646 | goto err2; |
647 | |
648 | size = sizeof(struct tx_sa) * IXGBE_IPSEC_MAX_SA_COUNT; |
649 | ipsec->tx_tbl = kzalloc(size, GFP_KERNEL); |
650 | if (!ipsec->tx_tbl) |
651 | goto err2; |
652 | |
653 | ipsec->num_rx_sa = 0; |
654 | ipsec->num_tx_sa = 0; |
655 | |
656 | adapter->ipsec = ipsec; |
657 | |
658 | adapter->netdev->xfrmdev_ops = &ixgbevf_xfrmdev_ops; |
659 | |
660 | #define IXGBEVF_ESP_FEATURES (NETIF_F_HW_ESP | \ |
661 | NETIF_F_HW_ESP_TX_CSUM | \ |
662 | NETIF_F_GSO_ESP) |
663 | |
664 | adapter->netdev->features |= IXGBEVF_ESP_FEATURES; |
665 | adapter->netdev->hw_enc_features |= IXGBEVF_ESP_FEATURES; |
666 | |
667 | return; |
668 | |
669 | err2: |
670 | kfree(objp: ipsec->rx_tbl); |
671 | kfree(objp: ipsec->tx_tbl); |
672 | kfree(objp: ipsec); |
673 | err1: |
674 | netdev_err(dev: adapter->netdev, format: "Unable to allocate memory for SA tables" ); |
675 | } |
676 | |
677 | /** |
678 | * ixgbevf_stop_ipsec_offload - tear down the IPsec offload |
679 | * @adapter: board private structure |
680 | **/ |
681 | void ixgbevf_stop_ipsec_offload(struct ixgbevf_adapter *adapter) |
682 | { |
683 | struct ixgbevf_ipsec *ipsec = adapter->ipsec; |
684 | |
685 | adapter->ipsec = NULL; |
686 | if (ipsec) { |
687 | kfree(objp: ipsec->rx_tbl); |
688 | kfree(objp: ipsec->tx_tbl); |
689 | kfree(objp: ipsec); |
690 | } |
691 | } |
692 | |