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