New upstream version 18.11-rc1
[deb_dpdk.git] / lib / librte_port / rte_port_sym_crypto.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018 Intel Corporation
3  */
4 #include <string.h>
5
6 #include <rte_common.h>
7 #include <rte_malloc.h>
8
9 #include "rte_port_sym_crypto.h"
10
11 /*
12  * Port Crypto Reader
13  */
14 #ifdef RTE_PORT_STATS_COLLECT
15
16 #define RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_IN_ADD(port, val) \
17         (port)->stats.n_pkts_in += (val)
18 #define RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_DROP_ADD(port, val) \
19         (port)->stats.n_pkts_drop += (val)
20
21 #else
22
23 #define RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_IN_ADD(port, val)
24 #define RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_DROP_ADD(port, val)
25
26 #endif
27
28 struct rte_port_sym_crypto_reader {
29         struct rte_port_in_stats stats;
30
31         uint8_t cryptodev_id;
32         uint16_t queue_id;
33         struct rte_crypto_op *ops[RTE_PORT_IN_BURST_SIZE_MAX];
34         rte_port_sym_crypto_reader_callback_fn f_callback;
35         void *arg_callback;
36 };
37
38 static void *
39 rte_port_sym_crypto_reader_create(void *params, int socket_id)
40 {
41         struct rte_port_sym_crypto_reader_params *conf =
42                         params;
43         struct rte_port_sym_crypto_reader *port;
44
45         /* Check input parameters */
46         if (conf == NULL) {
47                 RTE_LOG(ERR, PORT, "%s: params is NULL\n", __func__);
48                 return NULL;
49         }
50
51         /* Memory allocation */
52         port = rte_zmalloc_socket("PORT", sizeof(*port),
53                 RTE_CACHE_LINE_SIZE, socket_id);
54         if (port == NULL) {
55                 RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__);
56                 return NULL;
57         }
58
59         /* Initialization */
60         port->cryptodev_id = conf->cryptodev_id;
61         port->queue_id = conf->queue_id;
62         port->f_callback = conf->f_callback;
63         port->arg_callback = conf->arg_callback;
64
65         return port;
66 }
67
68 static int
69 rte_port_sym_crypto_reader_rx(void *port, struct rte_mbuf **pkts, uint32_t n_pkts)
70 {
71         struct rte_port_sym_crypto_reader *p =
72                         port;
73         uint16_t rx_ops_cnt, i, n = 0;
74
75         rx_ops_cnt = rte_cryptodev_dequeue_burst(p->cryptodev_id, p->queue_id,
76                         p->ops, n_pkts);
77
78         for (i = 0; i < rx_ops_cnt; i++) {
79                 struct rte_crypto_op *op = p->ops[i];
80
81                 /** Drop failed pkts */
82                 if (unlikely(op->status != RTE_CRYPTO_OP_STATUS_SUCCESS)) {
83                         rte_pktmbuf_free(op->sym->m_src);
84                         continue;
85                 }
86
87                 pkts[n++] = op->sym->m_src;
88         }
89
90         if (p->f_callback)
91                 (*p->f_callback)(pkts, n, p->arg_callback);
92
93         RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_IN_ADD(p, n);
94         RTE_PORT_SYM_CRYPTO_READER_STATS_PKTS_DROP_ADD(p, rx_ops_cnt - n);
95
96         return n;
97 }
98
99 static int
100 rte_port_sym_crypto_reader_free(void *port)
101 {
102         if (port == NULL) {
103                 RTE_LOG(ERR, PORT, "%s: port is NULL\n", __func__);
104                 return -EINVAL;
105         }
106
107         rte_free(port);
108
109         return 0;
110 }
111
112 static int rte_port_sym_crypto_reader_stats_read(void *port,
113         struct rte_port_in_stats *stats, int clear)
114 {
115         struct rte_port_sym_crypto_reader *p =
116                         port;
117
118         if (stats != NULL)
119                 memcpy(stats, &p->stats, sizeof(p->stats));
120
121         if (clear)
122                 memset(&p->stats, 0, sizeof(p->stats));
123
124         return 0;
125 }
126
127 /*
128  * Port crypto Writer
129  */
130 #ifdef RTE_PORT_STATS_COLLECT
131
132 #define RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(port, val) \
133         (port)->stats.n_pkts_in += (val)
134 #define RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_DROP_ADD(port, val) \
135         (port)->stats.n_pkts_drop += (val)
136
137 #else
138
139 #define RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(port, val)
140 #define RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_DROP_ADD(port, val)
141
142 #endif
143
144 struct rte_port_sym_crypto_writer {
145         struct rte_port_out_stats stats;
146
147         struct rte_crypto_op *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];
148
149         uint32_t tx_burst_sz;
150         uint32_t tx_buf_count;
151         uint64_t bsz_mask;
152
153         uint8_t cryptodev_id;
154         uint16_t queue_id;
155         uint16_t crypto_op_offset;
156 };
157
158 static void *
159 rte_port_sym_crypto_writer_create(void *params, int socket_id)
160 {
161         struct rte_port_sym_crypto_writer_params *conf =
162                         params;
163         struct rte_port_sym_crypto_writer *port;
164
165         /* Check input parameters */
166         if ((conf == NULL) ||
167                 (conf->tx_burst_sz == 0) ||
168                 (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) ||
169                 (!rte_is_power_of_2(conf->tx_burst_sz))) {
170                 RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__);
171                 return NULL;
172         }
173
174         /* Memory allocation */
175         port = rte_zmalloc_socket("PORT", sizeof(*port),
176                 RTE_CACHE_LINE_SIZE, socket_id);
177         if (port == NULL) {
178                 RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__);
179                 return NULL;
180         }
181
182         /* Initialization */
183         port->tx_burst_sz = conf->tx_burst_sz;
184         port->tx_buf_count = 0;
185         port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1);
186
187         port->cryptodev_id = conf->cryptodev_id;
188         port->queue_id = conf->queue_id;
189         port->crypto_op_offset = conf->crypto_op_offset;
190
191         return port;
192 }
193
194 static inline void
195 send_burst(struct rte_port_sym_crypto_writer *p)
196 {
197         uint32_t nb_tx;
198
199         nb_tx = rte_cryptodev_enqueue_burst(p->cryptodev_id, p->queue_id,
200                         p->tx_buf, p->tx_buf_count);
201
202         RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_DROP_ADD(p, p->tx_buf_count -
203                         nb_tx);
204         for (; nb_tx < p->tx_buf_count; nb_tx++)
205                 rte_pktmbuf_free(p->tx_buf[nb_tx]->sym->m_src);
206
207         p->tx_buf_count = 0;
208 }
209
210 static int
211 rte_port_sym_crypto_writer_tx(void *port, struct rte_mbuf *pkt)
212 {
213         struct rte_port_sym_crypto_writer *p =
214                         port;
215
216         p->tx_buf[p->tx_buf_count++] = (struct rte_crypto_op *)
217                         RTE_MBUF_METADATA_UINT8_PTR(pkt, p->crypto_op_offset);
218         RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(p, 1);
219         if (p->tx_buf_count >= p->tx_burst_sz)
220                 send_burst(p);
221
222         return 0;
223 }
224
225 static int
226 rte_port_sym_crypto_writer_tx_bulk(void *port,
227         struct rte_mbuf **pkts,
228         uint64_t pkts_mask)
229 {
230         struct rte_port_sym_crypto_writer *p =
231                         port;
232         uint64_t bsz_mask = p->bsz_mask;
233         uint32_t tx_buf_count = p->tx_buf_count;
234         uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
235                                         ((pkts_mask & bsz_mask) ^ bsz_mask);
236
237         if (expr == 0) {
238                 uint64_t n_pkts = __builtin_popcountll(pkts_mask);
239                 uint32_t i;
240
241                 RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(p, n_pkts);
242
243                 for (i = 0; i < n_pkts; i++)
244                         p->tx_buf[p->tx_buf_count++] = (struct rte_crypto_op *)
245                                         RTE_MBUF_METADATA_UINT8_PTR(pkts[i],
246                                                         p->crypto_op_offset);
247
248                 if (p->tx_buf_count >= p->tx_burst_sz)
249                         send_burst(p);
250         } else {
251                 for (; pkts_mask;) {
252                         uint32_t pkt_index = __builtin_ctzll(pkts_mask);
253                         uint64_t pkt_mask = 1LLU << pkt_index;
254                         struct rte_mbuf *pkt = pkts[pkt_index];
255
256                         p->tx_buf[tx_buf_count++] = (struct rte_crypto_op *)
257                                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
258                                                         p->crypto_op_offset);
259
260                         RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(p, 1);
261                         pkts_mask &= ~pkt_mask;
262                 }
263
264                 p->tx_buf_count = tx_buf_count;
265                 if (tx_buf_count >= p->tx_burst_sz)
266                         send_burst(p);
267         }
268
269         return 0;
270 }
271
272 static int
273 rte_port_sym_crypto_writer_flush(void *port)
274 {
275         struct rte_port_sym_crypto_writer *p =
276                         port;
277
278         if (p->tx_buf_count > 0)
279                 send_burst(p);
280
281         return 0;
282 }
283
284 static int
285 rte_port_sym_crypto_writer_free(void *port)
286 {
287         if (port == NULL) {
288                 RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__);
289                 return -EINVAL;
290         }
291
292         rte_port_sym_crypto_writer_flush(port);
293         rte_free(port);
294
295         return 0;
296 }
297
298 static int rte_port_sym_crypto_writer_stats_read(void *port,
299         struct rte_port_out_stats *stats, int clear)
300 {
301         struct rte_port_sym_crypto_writer *p =
302                         port;
303
304         if (stats != NULL)
305                 memcpy(stats, &p->stats, sizeof(p->stats));
306
307         if (clear)
308                 memset(&p->stats, 0, sizeof(p->stats));
309
310         return 0;
311 }
312
313 /*
314  * Port crypto Writer Nodrop
315  */
316 #ifdef RTE_PORT_STATS_COLLECT
317
318 #define RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val) \
319         (port)->stats.n_pkts_in += (val)
320 #define RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val) \
321         (port)->stats.n_pkts_drop += (val)
322
323 #else
324
325 #define RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_IN_ADD(port, val)
326 #define RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_DROP_ADD(port, val)
327
328 #endif
329
330 struct rte_port_sym_crypto_writer_nodrop {
331         struct rte_port_out_stats stats;
332
333         struct rte_crypto_op *tx_buf[2 * RTE_PORT_IN_BURST_SIZE_MAX];
334         uint32_t tx_burst_sz;
335         uint32_t tx_buf_count;
336         uint64_t bsz_mask;
337         uint64_t n_retries;
338
339         uint8_t cryptodev_id;
340         uint16_t queue_id;
341         uint16_t crypto_op_offset;
342 };
343
344 static void *
345 rte_port_sym_crypto_writer_nodrop_create(void *params, int socket_id)
346 {
347         struct rte_port_sym_crypto_writer_nodrop_params *conf =
348                 params;
349         struct rte_port_sym_crypto_writer_nodrop *port;
350
351         /* Check input parameters */
352         if ((conf == NULL) ||
353                 (conf->tx_burst_sz == 0) ||
354                 (conf->tx_burst_sz > RTE_PORT_IN_BURST_SIZE_MAX) ||
355                 (!rte_is_power_of_2(conf->tx_burst_sz))) {
356                 RTE_LOG(ERR, PORT, "%s: Invalid input parameters\n", __func__);
357                 return NULL;
358         }
359
360         /* Memory allocation */
361         port = rte_zmalloc_socket("PORT", sizeof(*port),
362                 RTE_CACHE_LINE_SIZE, socket_id);
363         if (port == NULL) {
364                 RTE_LOG(ERR, PORT, "%s: Failed to allocate port\n", __func__);
365                 return NULL;
366         }
367
368         /* Initialization */
369         port->cryptodev_id = conf->cryptodev_id;
370         port->queue_id = conf->queue_id;
371         port->crypto_op_offset = conf->crypto_op_offset;
372         port->tx_burst_sz = conf->tx_burst_sz;
373         port->tx_buf_count = 0;
374         port->bsz_mask = 1LLU << (conf->tx_burst_sz - 1);
375
376         /*
377          * When n_retries is 0 it means that we should wait for every packet to
378          * send no matter how many retries should it take. To limit number of
379          * branches in fast path, we use UINT64_MAX instead of branching.
380          */
381         port->n_retries = (conf->n_retries == 0) ? UINT64_MAX : conf->n_retries;
382
383         return port;
384 }
385
386 static inline void
387 send_burst_nodrop(struct rte_port_sym_crypto_writer_nodrop *p)
388 {
389         uint32_t nb_tx = 0, i;
390
391         nb_tx = rte_cryptodev_enqueue_burst(p->cryptodev_id, p->queue_id,
392                         p->tx_buf, p->tx_buf_count);
393
394         /* We sent all the packets in a first try */
395         if (nb_tx >= p->tx_buf_count) {
396                 p->tx_buf_count = 0;
397                 return;
398         }
399
400         for (i = 0; i < p->n_retries; i++) {
401                 nb_tx += rte_cryptodev_enqueue_burst(p->cryptodev_id,
402                                 p->queue_id, p->tx_buf + nb_tx,
403                                 p->tx_buf_count - nb_tx);
404
405                 /* We sent all the packets in more than one try */
406                 if (nb_tx >= p->tx_buf_count) {
407                         p->tx_buf_count = 0;
408                         return;
409                 }
410         }
411
412         /* We didn't send the packets in maximum allowed attempts */
413         RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_DROP_ADD(p,
414                         p->tx_buf_count - nb_tx);
415         for ( ; nb_tx < p->tx_buf_count; nb_tx++)
416                 rte_pktmbuf_free(p->tx_buf[nb_tx]->sym->m_src);
417
418         p->tx_buf_count = 0;
419 }
420
421 static int
422 rte_port_sym_crypto_writer_nodrop_tx(void *port, struct rte_mbuf *pkt)
423 {
424         struct rte_port_sym_crypto_writer_nodrop *p =
425                         port;
426
427         p->tx_buf[p->tx_buf_count++] = (struct rte_crypto_op *)
428                         RTE_MBUF_METADATA_UINT8_PTR(pkt, p->crypto_op_offset);
429         RTE_PORT_SYM_CRYPTO_WRITER_STATS_PKTS_IN_ADD(p, 1);
430         if (p->tx_buf_count >= p->tx_burst_sz)
431                 send_burst_nodrop(p);
432
433         return 0;
434 }
435
436 static int
437 rte_port_sym_crypto_writer_nodrop_tx_bulk(void *port,
438         struct rte_mbuf **pkts,
439         uint64_t pkts_mask)
440 {
441         struct rte_port_sym_crypto_writer_nodrop *p =
442                         port;
443
444         uint64_t bsz_mask = p->bsz_mask;
445         uint32_t tx_buf_count = p->tx_buf_count;
446         uint64_t expr = (pkts_mask & (pkts_mask + 1)) |
447                                         ((pkts_mask & bsz_mask) ^ bsz_mask);
448
449         if (expr == 0) {
450                 uint64_t n_pkts = __builtin_popcountll(pkts_mask);
451                 uint32_t i;
452
453                 RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_IN_ADD(p, n_pkts);
454
455                 for (i = 0; i < n_pkts; i++)
456                         p->tx_buf[p->tx_buf_count++] = (struct rte_crypto_op *)
457                                         RTE_MBUF_METADATA_UINT8_PTR(pkts[i],
458                                                         p->crypto_op_offset);
459
460                 if (p->tx_buf_count >= p->tx_burst_sz)
461                         send_burst_nodrop(p);
462         } else {
463                 for ( ; pkts_mask; ) {
464                         uint32_t pkt_index = __builtin_ctzll(pkts_mask);
465                         uint64_t pkt_mask = 1LLU << pkt_index;
466                         struct rte_mbuf *pkt = pkts[pkt_index];
467
468                         p->tx_buf[tx_buf_count++] = (struct rte_crypto_op *)
469                                         RTE_MBUF_METADATA_UINT8_PTR(pkt,
470                                                         p->crypto_op_offset);
471                         RTE_PORT_SYM_CRYPTO_WRITER_NODROP_STATS_PKTS_IN_ADD(p,
472                                         1);
473                         pkts_mask &= ~pkt_mask;
474                 }
475
476                 p->tx_buf_count = tx_buf_count;
477                 if (tx_buf_count >= p->tx_burst_sz)
478                         send_burst_nodrop(p);
479         }
480
481         return 0;
482 }
483
484 static int
485 rte_port_sym_crypto_writer_nodrop_flush(void *port)
486 {
487         struct rte_port_sym_crypto_writer_nodrop *p =
488                 port;
489
490         if (p->tx_buf_count > 0)
491                 send_burst_nodrop(p);
492
493         return 0;
494 }
495
496 static int
497 rte_port_sym_crypto_writer_nodrop_free(void *port)
498 {
499         if (port == NULL) {
500                 RTE_LOG(ERR, PORT, "%s: Port is NULL\n", __func__);
501                 return -EINVAL;
502         }
503
504         rte_port_sym_crypto_writer_nodrop_flush(port);
505         rte_free(port);
506
507         return 0;
508 }
509
510 static int rte_port_sym_crypto_writer_nodrop_stats_read(void *port,
511         struct rte_port_out_stats *stats, int clear)
512 {
513         struct rte_port_sym_crypto_writer_nodrop *p =
514                         port;
515
516         if (stats != NULL)
517                 memcpy(stats, &p->stats, sizeof(p->stats));
518
519         if (clear)
520                 memset(&p->stats, 0, sizeof(p->stats));
521
522         return 0;
523 }
524
525
526 /*
527  * Summary of port operations
528  */
529 struct rte_port_in_ops rte_port_sym_crypto_reader_ops = {
530         .f_create = rte_port_sym_crypto_reader_create,
531         .f_free = rte_port_sym_crypto_reader_free,
532         .f_rx = rte_port_sym_crypto_reader_rx,
533         .f_stats = rte_port_sym_crypto_reader_stats_read,
534 };
535
536 struct rte_port_out_ops rte_port_sym_crypto_writer_ops = {
537         .f_create = rte_port_sym_crypto_writer_create,
538         .f_free = rte_port_sym_crypto_writer_free,
539         .f_tx = rte_port_sym_crypto_writer_tx,
540         .f_tx_bulk = rte_port_sym_crypto_writer_tx_bulk,
541         .f_flush = rte_port_sym_crypto_writer_flush,
542         .f_stats = rte_port_sym_crypto_writer_stats_read,
543 };
544
545 struct rte_port_out_ops rte_port_sym_crypto_writer_nodrop_ops = {
546         .f_create = rte_port_sym_crypto_writer_nodrop_create,
547         .f_free = rte_port_sym_crypto_writer_nodrop_free,
548         .f_tx = rte_port_sym_crypto_writer_nodrop_tx,
549         .f_tx_bulk = rte_port_sym_crypto_writer_nodrop_tx_bulk,
550         .f_flush = rte_port_sym_crypto_writer_nodrop_flush,
551         .f_stats = rte_port_sym_crypto_writer_nodrop_stats_read,
552 };