Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2017 Intel Corporation
3 : : */
4 : :
5 : : #include <ethdev_driver.h>
6 : : #include <ethdev_pci.h>
7 : : #include <rte_ip.h>
8 : : #include <rte_jhash.h>
9 : : #include <rte_security_driver.h>
10 : : #include <rte_cryptodev.h>
11 : : #include <rte_flow.h>
12 : :
13 : : #include "base/ixgbe_type.h"
14 : : #include "base/ixgbe_api.h"
15 : : #include "ixgbe_ethdev.h"
16 : : #include "ixgbe_ipsec.h"
17 : :
18 : : #define IXGBE_REGISTER_POLL_WAIT_5_MS 5
19 : :
20 : : #define IXGBE_WAIT_RREAD \
21 : : IXGBE_WRITE_REG_THEN_POLL_MASK(hw, IXGBE_IPSRXIDX, reg_val, \
22 : : IPSRXIDX_READ, IXGBE_REGISTER_POLL_WAIT_5_MS)
23 : : #define IXGBE_WAIT_RWRITE \
24 : : IXGBE_WRITE_REG_THEN_POLL_MASK(hw, IXGBE_IPSRXIDX, reg_val, \
25 : : IPSRXIDX_WRITE, IXGBE_REGISTER_POLL_WAIT_5_MS)
26 : : #define IXGBE_WAIT_TREAD \
27 : : IXGBE_WRITE_REG_THEN_POLL_MASK(hw, IXGBE_IPSTXIDX, reg_val, \
28 : : IPSRXIDX_READ, IXGBE_REGISTER_POLL_WAIT_5_MS)
29 : : #define IXGBE_WAIT_TWRITE \
30 : : IXGBE_WRITE_REG_THEN_POLL_MASK(hw, IXGBE_IPSTXIDX, reg_val, \
31 : : IPSRXIDX_WRITE, IXGBE_REGISTER_POLL_WAIT_5_MS)
32 : :
33 : : #define CMP_IP(a, b) (\
34 : : (a).ipv6[0] == (b).ipv6[0] && \
35 : : (a).ipv6[1] == (b).ipv6[1] && \
36 : : (a).ipv6[2] == (b).ipv6[2] && \
37 : : (a).ipv6[3] == (b).ipv6[3])
38 : :
39 : : static inline void
40 : 0 : ixgbe_crypto_write_rx_ip(struct ixgbe_hw *hw, uint32_t idx,
41 : : const struct ipaddr *ip, bool enable)
42 : : {
43 : 0 : uint32_t reg_val = IPSRXIDX_WRITE | IPSRXIDX_TABLE_IP | (idx << 3);
44 : 0 : uint32_t addr[4] = {0};
45 : :
46 [ # # ]: 0 : if (enable)
47 : 0 : reg_val |= IPSRXIDX_RX_EN;
48 : :
49 [ # # ]: 0 : if (ip->type == IPv4)
50 : : /* only write last 4 bytes */
51 : 0 : addr[3] = ip->ipv4;
52 : : else
53 : : memcpy(addr, ip->ipv6, sizeof(addr));
54 : :
55 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXIPADDR(0), addr[0]);
56 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXIPADDR(1), addr[1]);
57 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXIPADDR(2), addr[2]);
58 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXIPADDR(3), addr[3]);
59 [ # # # # ]: 0 : IXGBE_WAIT_RWRITE;
60 : 0 : }
61 : :
62 : : static inline void
63 : 0 : ixgbe_crypto_write_rx_spi(struct ixgbe_hw *hw, uint32_t idx,
64 : : uint32_t spi, uint32_t ip_idx, bool enable)
65 : : {
66 : 0 : uint32_t reg_val = IPSRXIDX_WRITE | IPSRXIDX_TABLE_SPI | (idx << 3);
67 : :
68 [ # # ]: 0 : if (enable)
69 : 0 : reg_val |= IPSRXIDX_RX_EN;
70 : :
71 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXSPI, rte_cpu_to_be_32(spi));
72 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXIPIDX, ip_idx);
73 [ # # # # ]: 0 : IXGBE_WAIT_RWRITE;
74 : 0 : }
75 : :
76 : : static inline void
77 : 0 : ixgbe_crypto_write_rx_key(struct ixgbe_hw *hw, uint32_t idx,
78 : : const uint8_t *key, uint32_t salt, uint32_t mode, bool enable)
79 : : {
80 : 0 : uint32_t reg_val = IPSRXIDX_WRITE | IPSRXIDX_TABLE_KEY | (idx << 3);
81 : :
82 [ # # ]: 0 : if (enable)
83 : 0 : reg_val |= IPSRXIDX_RX_EN;
84 : :
85 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(0),
86 : : rte_cpu_to_be_32(*(const uint32_t *)&key[12]));
87 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(1),
88 : : rte_cpu_to_be_32(*(const uint32_t *)&key[8]));
89 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(2),
90 : : rte_cpu_to_be_32(*(const uint32_t *)&key[4]));
91 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXKEY(3),
92 : : rte_cpu_to_be_32(*(const uint32_t *)&key[0]));
93 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXSALT, rte_cpu_to_be_32(salt));
94 : 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSRXMOD, mode);
95 [ # # # # ]: 0 : IXGBE_WAIT_RWRITE;
96 : 0 : }
97 : :
98 : : static inline void
99 : 0 : ixgbe_crypto_write_tx_key(struct ixgbe_hw *hw, uint32_t idx,
100 : : const uint8_t *key, uint32_t salt, bool enable)
101 : : {
102 : 0 : uint32_t reg_val = IPSRXIDX_WRITE | (idx << 3);
103 : :
104 [ # # ]: 0 : if (enable)
105 : 0 : reg_val |= IPSRXIDX_TX_EN;
106 : :
107 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(0),
108 : : rte_cpu_to_be_32(*(const uint32_t *)&key[12]));
109 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(1),
110 : : rte_cpu_to_be_32(*(const uint32_t *)&key[8]));
111 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(2),
112 : : rte_cpu_to_be_32(*(const uint32_t *)&key[4]));
113 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSTXKEY(3),
114 : : rte_cpu_to_be_32(*(const uint32_t *)&key[0]));
115 [ # # ]: 0 : IXGBE_WRITE_REG(hw, IXGBE_IPSTXSALT, rte_cpu_to_be_32(salt));
116 [ # # # # ]: 0 : IXGBE_WAIT_TWRITE;
117 : 0 : }
118 : :
119 : : static void
120 : 0 : ixgbe_crypto_clear_ipsec_tables(struct rte_eth_dev *dev)
121 : : {
122 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
123 : : struct ixgbe_ipsec *priv = IXGBE_DEV_PRIVATE_TO_IPSEC(
124 : : dev->data->dev_private);
125 : 0 : const struct ipaddr ip = {0};
126 : 0 : const uint8_t key[16] = {0};
127 : : int i = 0;
128 : :
129 : : /* clear Rx IP table*/
130 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_RX_IP_COUNT; i++)
131 : 0 : ixgbe_crypto_write_rx_ip(hw, i, &ip, false);
132 : :
133 : : /* clear Rx SPI and Rx/Tx SA tables*/
134 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_SA_COUNT; i++) {
135 : 0 : ixgbe_crypto_write_rx_spi(hw, i, 0, 0, false);
136 : 0 : ixgbe_crypto_write_rx_key(hw, i, key, 0, 0, false);
137 : 0 : ixgbe_crypto_write_tx_key(hw, i, key, 0, false);
138 : : }
139 : :
140 : 0 : memset(priv->rx_ip_tbl, 0, sizeof(priv->rx_ip_tbl));
141 : 0 : memset(priv->rx_sa_tbl, 0, sizeof(priv->rx_sa_tbl));
142 : 0 : memset(priv->tx_sa_tbl, 0, sizeof(priv->tx_sa_tbl));
143 : 0 : }
144 : :
145 : : static int
146 : 0 : ixgbe_crypto_add_sa(struct ixgbe_crypto_session *ic_session)
147 : : {
148 : 0 : struct rte_eth_dev_data *dev_data = ic_session->dev_data;
149 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev_data->dev_private);
150 : : struct ixgbe_ipsec *priv = IXGBE_DEV_PRIVATE_TO_IPSEC(dev_data->dev_private);
151 : : int i, sa_index = -1;
152 : 0 : uint8_t key[16] = {0};
153 : :
154 [ # # ]: 0 : if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION) {
155 : : struct ixgbe_crypto_rx_ip_table *rxip;
156 : : struct ixgbe_crypto_rx_sa_table *rxsa;
157 : : int ip_index = -1, free_index = -1;
158 : :
159 : : /* Find a match in the IP table*/
160 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_RX_IP_COUNT; i++) {
161 [ # # # # : 0 : if (CMP_IP(priv->rx_ip_tbl[i].ip,
# # # # ]
162 : : ic_session->dst_ip)) {
163 : : ip_index = i;
164 : : break;
165 : : }
166 [ # # # # ]: 0 : if (free_index == -1 && priv->rx_ip_tbl[i].ref_count == 0)
167 : : free_index = i;
168 : : }
169 : : /* If no match, find a free entry in the IP table*/
170 [ # # ]: 0 : if (ip_index < 0)
171 : : ip_index = free_index;
172 : :
173 : : /* Fail if no match and no free entries*/
174 [ # # ]: 0 : if (ip_index < 0) {
175 : 0 : PMD_DRV_LOG(ERR, "No free entry left in the Rx IP table");
176 : 0 : return -ENOSPC;
177 : : }
178 : : rxip = &priv->rx_ip_tbl[ip_index];
179 : :
180 : : /* Find a free entry in the SA table*/
181 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_SA_COUNT; i++) {
182 [ # # ]: 0 : if (priv->rx_sa_tbl[i].used == 0) {
183 : : sa_index = i;
184 : : break;
185 : : }
186 : : }
187 : : /* Fail if no free entries*/
188 [ # # ]: 0 : if (sa_index < 0) {
189 : 0 : PMD_DRV_LOG(ERR, "No free entry left in the Rx SA table");
190 : 0 : return -ENOSPC;
191 : : }
192 : : rxsa = &priv->rx_sa_tbl[sa_index];
193 : :
194 : 0 : rxip->ref_count++;
195 [ # # ]: 0 : memcpy(&rxip->ip, &ic_session->dst_ip, sizeof(rxip->ip));
196 : :
197 : 0 : rxsa->spi = ic_session->spi;
198 : 0 : rxsa->ip_index = ip_index;
199 : 0 : rxsa->mode = IPSRXMOD_VALID | IPSRXMOD_PROTO | IPSRXMOD_DECRYPT;
200 [ # # ]: 0 : if (ic_session->dst_ip.type == IPv6)
201 : 0 : rxsa->mode |= IPSRXMOD_IPV6;
202 : :
203 : 0 : rxsa->used = 1;
204 : :
205 : : /* write IP table entry*/
206 : 0 : ixgbe_crypto_write_rx_ip(hw, ip_index, &rxip->ip, true);
207 : :
208 : : /* write SPI table entry*/
209 : 0 : ixgbe_crypto_write_rx_spi(hw, sa_index, rxsa->spi, ip_index, true);
210 : :
211 : : /* write Key table entry*/
212 : 0 : memcpy(key, ic_session->key, ic_session->key_len);
213 : :
214 : 0 : ixgbe_crypto_write_rx_key(hw, sa_index, key,
215 : 0 : ic_session->salt, rxsa->mode, true);
216 : :
217 : 0 : rte_memzero_explicit(key, sizeof(key));
218 : :
219 : : } else { /* sess->dir == RTE_CRYPTO_OUTBOUND */
220 : : struct ixgbe_crypto_tx_sa_table *txsa;
221 : :
222 : : /* Find a free entry in the SA table*/
223 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_SA_COUNT; i++) {
224 [ # # ]: 0 : if (priv->tx_sa_tbl[i].used == 0) {
225 : : sa_index = i;
226 : : break;
227 : : }
228 : : }
229 : : /* Fail if no free entries*/
230 [ # # ]: 0 : if (sa_index < 0) {
231 : 0 : PMD_DRV_LOG(ERR, "No free entry left in the Tx SA table");
232 : 0 : return -ENOSPC;
233 : : }
234 : : txsa = &priv->tx_sa_tbl[sa_index];
235 : :
236 : 0 : txsa->spi = ic_session->spi;
237 : 0 : txsa->used = 1;
238 : 0 : ic_session->sa_index = sa_index;
239 : :
240 : 0 : memcpy(key, ic_session->key, ic_session->key_len);
241 : :
242 : : /* write Key table entry*/
243 : 0 : ixgbe_crypto_write_tx_key(hw, sa_index, key, ic_session->salt, true);
244 : :
245 : 0 : rte_memzero_explicit(key, sizeof(key));
246 : : }
247 : :
248 : : return 0;
249 : : }
250 : :
251 : : static int
252 : 0 : ixgbe_crypto_remove_sa(struct ixgbe_crypto_session *ic_session)
253 : : {
254 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(ic_session->dev_data->dev_private);
255 : : struct ixgbe_ipsec *priv =
256 : : IXGBE_DEV_PRIVATE_TO_IPSEC(ic_session->dev_data->dev_private);
257 : 0 : const uint8_t key[16] = {0};
258 : : int i, sa_index = -1;
259 : :
260 [ # # ]: 0 : if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION) {
261 : : struct ixgbe_crypto_rx_ip_table *rxip;
262 : : struct ixgbe_crypto_rx_sa_table *rxsa;
263 : : int ip_index = -1;
264 : :
265 : : /* Find a match in the IP table*/
266 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_RX_IP_COUNT; i++) {
267 [ # # # # : 0 : if (CMP_IP(priv->rx_ip_tbl[i].ip, ic_session->dst_ip)) {
# # # # ]
268 : : ip_index = i;
269 : : break;
270 : : }
271 : : }
272 : :
273 : : /* Fail if no match*/
274 [ # # ]: 0 : if (ip_index < 0) {
275 : 0 : PMD_DRV_LOG(ERR, "Entry not found in the Rx IP table");
276 : 0 : return -ENOENT;
277 : : }
278 : : rxip = &priv->rx_ip_tbl[ip_index];
279 : :
280 : : /* Find a free entry in the SA table*/
281 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_SA_COUNT; i++) {
282 [ # # ]: 0 : if (priv->rx_sa_tbl[i].spi == ic_session->spi) {
283 : : sa_index = i;
284 : : break;
285 : : }
286 : : }
287 : : /* Fail if no match*/
288 [ # # ]: 0 : if (sa_index < 0) {
289 : 0 : PMD_DRV_LOG(ERR, "Entry not found in the Rx SA table");
290 : 0 : return -ENOENT;
291 : : }
292 : : rxsa = &priv->rx_sa_tbl[sa_index];
293 : :
294 : : /* Disable and clear Rx SPI and key table entries*/
295 : 0 : ixgbe_crypto_write_rx_spi(hw, sa_index, 0, 0, false);
296 : 0 : ixgbe_crypto_write_rx_key(hw, sa_index, key, 0, 0, false);
297 : :
298 : : /* Clear the SA table entry*/
299 : 0 : *rxsa = (struct ixgbe_crypto_rx_sa_table){0};
300 : :
301 : : /* If last used then clear the IP table entry*/
302 : 0 : rxip->ref_count--;
303 [ # # ]: 0 : if (rxip->ref_count == 0) {
304 : 0 : const struct ipaddr ip = {0};
305 : 0 : ixgbe_crypto_write_rx_ip(hw, ip_index, &ip, false);
306 : 0 : *rxip = (struct ixgbe_crypto_rx_ip_table){0};
307 : : }
308 : : } else { /* session->dir == RTE_CRYPTO_OUTBOUND */
309 : : struct ixgbe_crypto_tx_sa_table *txsa;
310 : :
311 : : /* Find a match in the SA table*/
312 [ # # ]: 0 : for (i = 0; i < IPSEC_MAX_SA_COUNT; i++) {
313 [ # # ]: 0 : if (priv->tx_sa_tbl[i].spi == ic_session->spi) {
314 : : sa_index = i;
315 : : break;
316 : : }
317 : : }
318 : : /* Fail if no match entries*/
319 [ # # ]: 0 : if (sa_index < 0) {
320 : 0 : PMD_DRV_LOG(ERR, "Entry not found in the Tx SA table");
321 : : return -ENOENT;
322 : : }
323 : : txsa = &priv->tx_sa_tbl[sa_index];
324 : :
325 : 0 : ixgbe_crypto_write_tx_key(hw, sa_index, key, 0, false);
326 : 0 : *txsa = (struct ixgbe_crypto_tx_sa_table){0};
327 : : }
328 : :
329 : : return 0;
330 : : }
331 : :
332 : : static int
333 : 0 : ixgbe_crypto_create_session(void *device,
334 : : struct rte_security_session_conf *conf,
335 : : struct rte_security_session *session)
336 : : {
337 : : struct rte_eth_dev *eth_dev = (struct rte_eth_dev *)device;
338 : 0 : struct ixgbe_crypto_session *ic_session = SECURITY_GET_SESS_PRIV(session);
339 : : struct rte_crypto_aead_xform *aead_xform;
340 : 0 : struct rte_eth_conf *dev_conf = ð_dev->data->dev_conf;
341 : :
342 [ # # ]: 0 : if (conf->crypto_xform->type != RTE_CRYPTO_SYM_XFORM_AEAD ||
343 [ # # ]: 0 : conf->crypto_xform->aead.algo !=
344 : : RTE_CRYPTO_AEAD_AES_GCM) {
345 : 0 : PMD_DRV_LOG(ERR, "Unsupported crypto transformation mode");
346 : 0 : return -ENOTSUP;
347 : : }
348 : : aead_xform = &conf->crypto_xform->aead;
349 : :
350 : : /* Only 16-byte keys are supported. */
351 [ # # ]: 0 : if (aead_xform->key.length != 16) {
352 : 0 : PMD_DRV_LOG(ERR, "Unsupported key length %u", aead_xform->key.length);
353 : 0 : return -ENOTSUP;
354 : : }
355 : :
356 [ # # ]: 0 : if (conf->ipsec.direction == RTE_SECURITY_IPSEC_SA_DIR_INGRESS) {
357 [ # # ]: 0 : if (dev_conf->rxmode.offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
358 : 0 : ic_session->op = IXGBE_OP_AUTHENTICATED_DECRYPTION;
359 : : } else {
360 : 0 : PMD_DRV_LOG(ERR, "IPsec decryption not enabled");
361 : 0 : return -ENOTSUP;
362 : : }
363 : : } else {
364 [ # # ]: 0 : if (dev_conf->txmode.offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
365 : 0 : ic_session->op = IXGBE_OP_AUTHENTICATED_ENCRYPTION;
366 : : } else {
367 : 0 : PMD_DRV_LOG(ERR, "IPsec encryption not enabled");
368 : 0 : return -ENOTSUP;
369 : : }
370 : : }
371 : :
372 : 0 : ic_session->key = aead_xform->key.data;
373 : 0 : ic_session->key_len = aead_xform->key.length;
374 : 0 : memcpy(&ic_session->salt,
375 [ # # ]: 0 : &aead_xform->key.data[aead_xform->key.length], 4);
376 : 0 : ic_session->spi = conf->ipsec.spi;
377 : 0 : ic_session->dev_data = eth_dev->data;
378 : :
379 [ # # ]: 0 : if (ic_session->op == IXGBE_OP_AUTHENTICATED_ENCRYPTION) {
380 [ # # ]: 0 : if (ixgbe_crypto_add_sa(ic_session)) {
381 : 0 : PMD_DRV_LOG(ERR, "Failed to add SA");
382 : 0 : return -EPERM;
383 : : }
384 : : }
385 : :
386 : : return 0;
387 : : }
388 : :
389 : : static unsigned int
390 : 0 : ixgbe_crypto_session_get_size(__rte_unused void *device)
391 : : {
392 : 0 : return sizeof(struct ixgbe_crypto_session);
393 : : }
394 : :
395 : : static int
396 : 0 : ixgbe_crypto_remove_session(void *device,
397 : : struct rte_security_session *session)
398 : : {
399 : : struct rte_eth_dev *eth_dev = device;
400 : 0 : struct ixgbe_crypto_session *ic_session = SECURITY_GET_SESS_PRIV(session);
401 : :
402 [ # # ]: 0 : if (eth_dev->data != ic_session->dev_data) {
403 : 0 : PMD_DRV_LOG(ERR, "Session not bound to this device");
404 : 0 : return -ENODEV;
405 : : }
406 : :
407 [ # # ]: 0 : if (ixgbe_crypto_remove_sa(ic_session)) {
408 : 0 : PMD_DRV_LOG(ERR, "Failed to remove session");
409 : 0 : return -EFAULT;
410 : : }
411 : :
412 : : memset(ic_session, 0, sizeof(struct ixgbe_crypto_session));
413 : 0 : return 0;
414 : : }
415 : :
416 : : static inline uint8_t
417 : : ixgbe_crypto_compute_pad_len(struct rte_mbuf *m)
418 : : {
419 : 0 : if (m->nb_segs == 1) {
420 : : /* 16 bytes ICV + 2 bytes ESP trailer + payload padding size
421 : : * payload padding size is stored at <pkt_len - 18>
422 : : */
423 : 0 : uint8_t *esp_pad_len = rte_pktmbuf_mtod_offset(m, uint8_t *,
424 : : rte_pktmbuf_pkt_len(m) -
425 : : (ESP_TRAILER_SIZE + ESP_ICV_SIZE));
426 : 0 : return *esp_pad_len + ESP_TRAILER_SIZE + ESP_ICV_SIZE;
427 : : }
428 : : return 0;
429 : : }
430 : :
431 : : static int
432 : 0 : ixgbe_crypto_update_mb(void *device __rte_unused,
433 : : struct rte_security_session *session,
434 : : struct rte_mbuf *m, void *params __rte_unused)
435 : : {
436 : : struct ixgbe_crypto_session *ic_session = SECURITY_GET_SESS_PRIV(session);
437 [ # # ]: 0 : if (ic_session->op == IXGBE_OP_AUTHENTICATED_ENCRYPTION) {
438 : : union ixgbe_crypto_tx_desc_md *mdata =
439 : : (union ixgbe_crypto_tx_desc_md *)
440 : : rte_security_dynfield(m);
441 : 0 : mdata->enc = 1;
442 [ # # ]: 0 : mdata->sa_idx = ic_session->sa_index;
443 : 0 : mdata->pad_len = ixgbe_crypto_compute_pad_len(m);
444 : : }
445 : 0 : return 0;
446 : : }
447 : :
448 : :
449 : : static const struct rte_security_capability *
450 : 0 : ixgbe_crypto_capabilities_get(void *device __rte_unused)
451 : : {
452 : : static const struct rte_cryptodev_capabilities
453 : : aes_gcm_gmac_crypto_capabilities[] = {
454 : : { /* AES GMAC (128-bit) */
455 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
456 : : {.sym = {
457 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AUTH,
458 : : {.auth = {
459 : : .algo = RTE_CRYPTO_AUTH_AES_GMAC,
460 : : .block_size = 16,
461 : : .key_size = {
462 : : .min = 16,
463 : : .max = 16,
464 : : .increment = 0
465 : : },
466 : : .digest_size = {
467 : : .min = 16,
468 : : .max = 16,
469 : : .increment = 0
470 : : },
471 : : .iv_size = {
472 : : .min = 12,
473 : : .max = 12,
474 : : .increment = 0
475 : : }
476 : : }, }
477 : : }, }
478 : : },
479 : : { /* AES GCM (128-bit) */
480 : : .op = RTE_CRYPTO_OP_TYPE_SYMMETRIC,
481 : : {.sym = {
482 : : .xform_type = RTE_CRYPTO_SYM_XFORM_AEAD,
483 : : {.aead = {
484 : : .algo = RTE_CRYPTO_AEAD_AES_GCM,
485 : : .block_size = 16,
486 : : .key_size = {
487 : : .min = 16,
488 : : .max = 16,
489 : : .increment = 0
490 : : },
491 : : .digest_size = {
492 : : .min = 16,
493 : : .max = 16,
494 : : .increment = 0
495 : : },
496 : : .aad_size = {
497 : : .min = 0,
498 : : .max = 65535,
499 : : .increment = 1
500 : : },
501 : : .iv_size = {
502 : : .min = 12,
503 : : .max = 12,
504 : : .increment = 0
505 : : }
506 : : }, }
507 : : }, }
508 : : },
509 : : {
510 : : .op = RTE_CRYPTO_OP_TYPE_UNDEFINED,
511 : : {.sym = {
512 : : .xform_type = RTE_CRYPTO_SYM_XFORM_NOT_SPECIFIED
513 : : }, }
514 : : },
515 : : };
516 : :
517 : : static const struct rte_security_capability
518 : : ixgbe_security_capabilities[] = {
519 : : { /* IPsec Inline Crypto ESP Transport Egress */
520 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
521 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
522 : : {.ipsec = {
523 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
524 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
525 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
526 : : .options = { 0 }
527 : : } },
528 : : .crypto_capabilities = aes_gcm_gmac_crypto_capabilities,
529 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
530 : : },
531 : : { /* IPsec Inline Crypto ESP Transport Ingress */
532 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
533 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
534 : : {.ipsec = {
535 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
536 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TRANSPORT,
537 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
538 : : .options = { 0 }
539 : : } },
540 : : .crypto_capabilities = aes_gcm_gmac_crypto_capabilities,
541 : : .ol_flags = 0
542 : : },
543 : : { /* IPsec Inline Crypto ESP Tunnel Egress */
544 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
545 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
546 : : {.ipsec = {
547 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
548 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
549 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_EGRESS,
550 : : .options = { 0 }
551 : : } },
552 : : .crypto_capabilities = aes_gcm_gmac_crypto_capabilities,
553 : : .ol_flags = RTE_SECURITY_TX_OLOAD_NEED_MDATA
554 : : },
555 : : { /* IPsec Inline Crypto ESP Tunnel Ingress */
556 : : .action = RTE_SECURITY_ACTION_TYPE_INLINE_CRYPTO,
557 : : .protocol = RTE_SECURITY_PROTOCOL_IPSEC,
558 : : {.ipsec = {
559 : : .proto = RTE_SECURITY_IPSEC_SA_PROTO_ESP,
560 : : .mode = RTE_SECURITY_IPSEC_SA_MODE_TUNNEL,
561 : : .direction = RTE_SECURITY_IPSEC_SA_DIR_INGRESS,
562 : : .options = { 0 }
563 : : } },
564 : : .crypto_capabilities = aes_gcm_gmac_crypto_capabilities,
565 : : .ol_flags = 0
566 : : },
567 : : {
568 : : .action = RTE_SECURITY_ACTION_TYPE_NONE
569 : : }
570 : : };
571 : :
572 : 0 : return ixgbe_security_capabilities;
573 : : }
574 : :
575 : :
576 : : int
577 : 0 : ixgbe_crypto_enable_ipsec(struct rte_eth_dev *dev)
578 : : {
579 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
580 : : uint32_t reg;
581 : : uint64_t rx_offloads;
582 : : uint64_t tx_offloads;
583 : :
584 : 0 : rx_offloads = dev->data->dev_conf.rxmode.offloads;
585 : 0 : tx_offloads = dev->data->dev_conf.txmode.offloads;
586 : :
587 : : /* sanity checks */
588 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_TCP_LRO) {
589 : 0 : PMD_DRV_LOG(ERR, "RSC and IPsec not supported");
590 : 0 : return -1;
591 : : }
592 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_KEEP_CRC) {
593 : 0 : PMD_DRV_LOG(ERR, "HW CRC strip needs to be enabled for IPsec");
594 : 0 : return -1;
595 : : }
596 : :
597 : :
598 : : /* Set IXGBE_SECTXBUFFAF to 0x15 as required in the datasheet*/
599 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECTXBUFFAF, 0x15);
600 : :
601 : : /* IFG needs to be set to 3 when we are using security. Otherwise a Tx
602 : : * hang will occur with heavy traffic.
603 : : */
604 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
605 : 0 : reg = (reg & 0xFFFFFFF0) | 0x3;
606 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
607 : :
608 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
609 : 0 : reg |= IXGBE_HLREG0_TXCRCEN | IXGBE_HLREG0_RXCRCSTRP;
610 : 0 : IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg);
611 : :
612 [ # # ]: 0 : if (rx_offloads & RTE_ETH_RX_OFFLOAD_SECURITY) {
613 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, 0);
614 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
615 [ # # ]: 0 : if (reg != 0) {
616 : 0 : PMD_DRV_LOG(ERR, "Error enabling Rx Crypto");
617 : 0 : return -1;
618 : : }
619 : : }
620 [ # # ]: 0 : if (tx_offloads & RTE_ETH_TX_OFFLOAD_SECURITY) {
621 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL,
622 : : IXGBE_SECTXCTRL_STORE_FORWARD);
623 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
624 [ # # ]: 0 : if (reg != IXGBE_SECTXCTRL_STORE_FORWARD) {
625 : 0 : PMD_DRV_LOG(ERR, "Error enabling Rx Crypto");
626 : 0 : return -1;
627 : : }
628 : : }
629 : :
630 : 0 : ixgbe_crypto_clear_ipsec_tables(dev);
631 : :
632 : 0 : return 0;
633 : : }
634 : :
635 : : int
636 : 0 : ixgbe_crypto_add_ingress_sa_from_flow(struct rte_security_session *sess,
637 : : const struct ip_spec *spec)
638 : : {
639 : 0 : struct ixgbe_crypto_session *ic_session = SECURITY_GET_SESS_PRIV(sess);
640 : :
641 [ # # ]: 0 : if (ic_session->op == IXGBE_OP_AUTHENTICATED_DECRYPTION) {
642 [ # # ]: 0 : if (spec->is_ipv6) {
643 : : const struct rte_flow_item_ipv6 *ipv6 = &spec->spec.ipv6;
644 : 0 : ic_session->src_ip.type = IPv6;
645 : 0 : ic_session->dst_ip.type = IPv6;
646 : 0 : memcpy(ic_session->src_ip.ipv6,
647 : 0 : &ipv6->hdr.src_addr, 16);
648 : 0 : memcpy(ic_session->dst_ip.ipv6,
649 : 0 : &ipv6->hdr.dst_addr, 16);
650 : : } else {
651 : : const struct rte_flow_item_ipv4 *ipv4 = &spec->spec.ipv4;
652 : 0 : ic_session->src_ip.type = IPv4;
653 : 0 : ic_session->dst_ip.type = IPv4;
654 : 0 : ic_session->src_ip.ipv4 = ipv4->hdr.src_addr;
655 : 0 : ic_session->dst_ip.ipv4 = ipv4->hdr.dst_addr;
656 : : }
657 : 0 : return ixgbe_crypto_add_sa(ic_session);
658 : : }
659 : :
660 : : return 0;
661 : : }
662 : :
663 : : static struct rte_security_ops ixgbe_security_ops = {
664 : : .session_create = ixgbe_crypto_create_session,
665 : : .session_update = NULL,
666 : : .session_get_size = ixgbe_crypto_session_get_size,
667 : : .session_stats_get = NULL,
668 : : .session_destroy = ixgbe_crypto_remove_session,
669 : : .set_pkt_metadata = ixgbe_crypto_update_mb,
670 : : .capabilities_get = ixgbe_crypto_capabilities_get
671 : : };
672 : :
673 : : static int
674 : : ixgbe_crypto_capable(struct rte_eth_dev *dev)
675 : : {
676 : 0 : struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
677 : : uint32_t reg_i, reg, capable = 1;
678 : : /* test if rx crypto can be enabled and then write back initial value*/
679 : 0 : reg_i = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
680 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, 0);
681 : 0 : reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
682 [ # # ]: 0 : if (reg != 0)
683 : : capable = 0;
684 : 0 : IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, reg_i);
685 : 0 : return capable;
686 : : }
687 : :
688 : : int
689 : 0 : ixgbe_ipsec_ctx_create(struct rte_eth_dev *dev)
690 : : {
691 : : struct rte_security_ctx *ctx = NULL;
692 : :
693 [ # # ]: 0 : if (ixgbe_crypto_capable(dev)) {
694 : 0 : ctx = rte_malloc("rte_security_instances_ops",
695 : : sizeof(struct rte_security_ctx), 0);
696 [ # # ]: 0 : if (ctx) {
697 : 0 : ctx->device = (void *)dev;
698 : 0 : ctx->ops = &ixgbe_security_ops;
699 : 0 : ctx->sess_cnt = 0;
700 : 0 : dev->security_ctx = ctx;
701 : : } else {
702 : : return -ENOMEM;
703 : : }
704 : : }
705 [ # # ]: 0 : if (rte_security_dynfield_register() < 0)
706 : 0 : return -rte_errno;
707 : : return 0;
708 : : }
|