Trivial: Clean up some typos.
[vpp.git] / src / plugins / dpdk / ipsec / cli.c
1 /*
2  * Copyright (c) 2017 Intel and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/vnet.h>
17 #include <dpdk/device/dpdk.h>
18 #include <dpdk/ipsec/ipsec.h>
19
20 static u8 *
21 format_crypto (u8 * s, va_list * args)
22 {
23   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
24   crypto_dev_t *dev = va_arg (*args, crypto_dev_t *);
25   crypto_drv_t *drv = vec_elt_at_index (dcm->drv, dev->drv_id);
26   u64 feat, mask;
27   u32 i;
28   char *pre = "  ";
29
30   s = format (s, "%-25s%-20s%-10s\n", dev->name, drv->name,
31               rte_cryptodevs[dev->id].data->dev_started ? "up" : "down");
32   s = format (s, "  numa_node %u, max_queues %u\n", dev->numa, dev->max_qp);
33   s = format (s, "  free_resources %u, used_resources %u\n",
34               vec_len (dev->free_resources), vec_len (dev->used_resources));
35
36   if (dev->features)
37     {
38       for (mask = 1; mask != 0; mask <<= 1)
39         {
40           feat = dev->features & mask;
41           if (feat)
42             {
43               s =
44                 format (s, "%s%s", pre,
45                         rte_cryptodev_get_feature_name (feat));
46               pre = ", ";
47             }
48         }
49       s = format (s, "\n");
50     }
51
52   s = format (s, "  Cipher:");
53   pre = " ";
54   for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
55     if (dev->cipher_support[i])
56       {
57         s = format (s, "%s%s", pre, dcm->cipher_algs[i].name);
58         pre = ", ";
59       }
60   s = format (s, "\n");
61
62   s = format (s, "  Auth:");
63   pre = " ";
64   for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
65     if (dev->auth_support[i])
66       {
67         s = format (s, "%s%s", pre, dcm->auth_algs[i].name);
68         pre = ", ";
69       }
70   s = format (s, "\n\n");
71
72   return s;
73 }
74
75 static clib_error_t *
76 show_dpdk_crypto_fn (vlib_main_t * vm, unformat_input_t * input,
77                      vlib_cli_command_t * cmd)
78 {
79   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
80   crypto_dev_t *dev;
81
82   /* *INDENT-OFF* */
83   vec_foreach (dev, dcm->dev)
84     vlib_cli_output (vm, "%U", format_crypto, dev);
85   /* *INDENT-ON* */
86
87   return NULL;
88 }
89
90 /*?
91  * This command is used to display the DPDK Crypto device information.
92  *
93  * @cliexpar
94  * Example of how to display the DPDK Crypto device information:
95  * @cliexsart{show dpdk crypto devices}
96  * vpp# show dpdk crypto devices
97  *   cryptodev_aesni_mb_pmd   crypto_aesni_mb     down
98  *   numa_node 1, max_queues 8
99  *   free_resources 2, used_resources 2
100  *   SYMMETRIC_CRYPTO, SYM_OPERATION_CHAINING, CPU_AVX2, CPU_AESNI
101  *   Cipher: aes-cbc-128, aes-cbc-192, aes-cbc-256, aes-ctr-128, aes-ctr-192, aes-ctr-256
102  *   Auth: md5-96, sha1-96, sha-256-128, sha-384-192, sha-512-256
103  *
104  * cryptodev_aesni_gcm_pmd  crypto_aesni_gcm    down
105  *   numa_node 1, max_queues 8
106  *   free_resources 2, used_resources 2
107  *   SYMMETRIC_CRYPTO, SYM_OPERATION_CHAINING, CPU_AVX2, CPU_AESNI, MBUF_SCATTER_GATHER
108  *   Cipher: aes-gcm-128, aes-gcm-192, aes-gcm-256
109  *   Auth:
110  * @cliexend
111  * Example of displaying the DPDK Crypto device data when enabled:
112  * @cliexend
113 ?*/
114 /* *INDENT-OFF* */
115 VLIB_CLI_COMMAND (show_dpdk_crypto, static) = {
116     .path = "show dpdk crypto devices",
117     .short_help = "show dpdk crypto devices",
118     .function = show_dpdk_crypto_fn,
119 };
120
121 /* *INDENT-ON* */
122 static u8 *
123 format_crypto_worker (u8 * s, va_list * args)
124 {
125   u32 thread_idx = va_arg (*args, u32);
126   u8 verbose = (u8) va_arg (*args, u32);
127   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
128   crypto_worker_main_t *cwm;
129   crypto_resource_t *res;
130   u16 *res_idx;
131   char *pre, *ind;
132   u32 i;
133
134   cwm = vec_elt_at_index (dcm->workers_main, thread_idx);
135
136   s = format (s, "Thread %u (%v):\n", thread_idx,
137               vlib_worker_threads[thread_idx].name);
138
139   /* *INDENT-OFF* */
140   vec_foreach (res_idx, cwm->resource_idx)
141     {
142       ind = "  ";
143       res = vec_elt_at_index (dcm->resource, res_idx[0]);
144       s = format (s, "%s%-20s dev-id %2u inbound-queue %2u outbound-queue %2u\n",
145                   ind, vec_elt_at_index (dcm->dev, res->dev_id)->name,
146                   res->dev_id, res->qp_id, res->qp_id + 1);
147
148       ind = "    ";
149       if (verbose)
150         {
151           s = format (s, "%sCipher:", ind);
152           pre = " ";
153           for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
154             if (cwm->cipher_resource_idx[i] == res_idx[0])
155               {
156                 s = format (s, "%s%s", pre, dcm->cipher_algs[i].name);
157                 pre = ", ";
158               }
159           s = format (s, "\n");
160
161           s = format (s, "%sAuth:", ind);
162           pre = " ";
163           for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
164             if (cwm->auth_resource_idx[i] == res_idx[0])
165               {
166                 s = format (s, "%s%s", pre, dcm->auth_algs[i].name);
167                 pre = ", ";
168               }
169           s = format (s, "\n");
170         }
171     }
172   /* *INDENT-ON* */
173
174   return s;
175 }
176
177 static clib_error_t *
178 common_crypto_placement_fn (vlib_main_t * vm, unformat_input_t * input,
179                             vlib_cli_command_t * cmd, u8 verbose)
180 {
181   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
182   clib_error_t *error = NULL;
183   u32 i;
184   u8 skip_master;
185
186   if (!dcm->enabled)
187     {
188       vlib_cli_output (vm, "\nDPDK Cryptodev support is disabled\n");
189       return error;
190     }
191
192   skip_master = vlib_num_workers () > 0;
193
194   /* *INDENT-OFF* */
195   vec_foreach_index (i, dcm->workers_main)
196     {
197       if (i < skip_master)
198         continue;
199
200       vlib_cli_output (vm, "%U\n", format_crypto_worker, i, verbose);
201     }
202   /* *INDENT-ON* */
203
204   return error;
205 }
206
207 static clib_error_t *
208 show_dpdk_crypto_placement_fn (vlib_main_t * vm, unformat_input_t * input,
209                                vlib_cli_command_t * cmd)
210 {
211   return common_crypto_placement_fn (vm, input, cmd, 0);
212 }
213
214 static clib_error_t *
215 show_dpdk_crypto_placement_v_fn (vlib_main_t * vm, unformat_input_t * input,
216                                  vlib_cli_command_t * cmd)
217 {
218   return common_crypto_placement_fn (vm, input, cmd, 1);
219 }
220
221 /*?
222  * This command is used to display the DPDK Crypto device placement.
223  *
224  * @cliexpar
225  * Example of displaying the DPDK Crypto device placement:
226  * @cliexstart{show dpdk crypto placement}
227  * vpp# show dpdk crypto placement
228  * Thread 1 (vpp_wk_0):
229  *   cryptodev_aesni_mb_p dev-id  0 inbound-queue  0 outbound-queue  1
230  *   cryptodev_aesni_gcm_ dev-id  1 inbound-queue  0 outbound-queue  1
231  *
232  * Thread 2 (vpp_wk_1):
233  *   cryptodev_aesni_mb_p dev-id  0 inbound-queue  2 outbound-queue  3
234  *   cryptodev_aesni_gcm_ dev-id  1 inbound-queue  2 outbound-queue  3
235  * @cliexend
236 ?*/
237 /* *INDENT-OFF* */
238 VLIB_CLI_COMMAND (show_dpdk_crypto_placement, static) = {
239     .path = "show dpdk crypto placement",
240     .short_help = "show dpdk crypto placement",
241     .function = show_dpdk_crypto_placement_fn,
242 };
243 /* *INDENT-ON* */
244
245 /*?
246  * This command is used to display the DPDK Crypto device placement
247  * with verbose output.
248  *
249  * @cliexpar
250  * Example of displaying the DPDK Crypto device placement verbose:
251  * @cliexstart{show dpdk crypto placement verbose}
252  * vpp# show dpdk crypto placement verbose
253  * Thread 1 (vpp_wk_0):
254  *   cryptodev_aesni_mb_p dev-id  0 inbound-queue  0 outbound-queue  1
255  *     Cipher: aes-cbc-128, aes-cbc-192, aes-cbc-256, aes-ctr-128, aes-ctr-192, aes-ctr-256
256  *     Auth: md5-96, sha1-96, sha-256-128, sha-384-192, sha-512-256
257  *     cryptodev_aesni_gcm_ dev-id  1 inbound-queue  0 outbound-queue  1
258  *     Cipher: aes-gcm-128, aes-gcm-192, aes-gcm-256
259  *     Auth:
260  *
261  * Thread 2 (vpp_wk_1):
262  *   cryptodev_aesni_mb_p dev-id  0 inbound-queue  2 outbound-queue  3
263  *     Cipher: aes-cbc-128, aes-cbc-192, aes-cbc-256, aes-ctr-128, aes-ctr-192, aes-ctr-256
264  *     Auth: md5-96, sha1-96, sha-256-128, sha-384-192, sha-512-256
265  *     cryptodev_aesni_gcm_ dev-id  1 inbound-queue  2 outbound-queue  3
266  *     Cipher: aes-gcm-128, aes-gcm-192, aes-gcm-256
267  *     Auth:
268  *
269  * @cliexend
270 ?*/
271 /* *INDENT-OFF* */
272 VLIB_CLI_COMMAND (show_dpdk_crypto_placement_v, static) = {
273     .path = "show dpdk crypto placement verbose",
274     .short_help = "show dpdk crypto placement verbose",
275     .function = show_dpdk_crypto_placement_v_fn,
276 };
277 /* *INDENT-ON* */
278
279 static clib_error_t *
280 set_dpdk_crypto_placement_fn (vlib_main_t * vm,
281                               unformat_input_t * input,
282                               vlib_cli_command_t * cmd)
283 {
284   unformat_input_t _line_input, *line_input = &_line_input;
285   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
286   crypto_worker_main_t *cwm;
287   crypto_dev_t *dev;
288   u32 thread_idx, i;
289   u16 res_idx, *idx;
290   u8 dev_idx, auto_en = 0;
291
292   if (!unformat_user (input, unformat_line_input, line_input))
293     return clib_error_return (0, "invalid syntax");
294
295   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
296     {
297       if (unformat (line_input, "%u %u", &dev_idx, &thread_idx))
298         ;
299       else if (unformat (line_input, "auto"))
300         auto_en = 1;
301       else
302         {
303           unformat_free (line_input);
304           return clib_error_return (0, "parse error: '%U'",
305                                     format_unformat_error, line_input);
306         }
307     }
308
309   unformat_free (line_input);
310
311   if (auto_en)
312     {
313       crypto_auto_placement ();
314       return 0;
315     }
316
317   /* TODO support device name */
318
319   if (!(dev_idx < vec_len (dcm->dev)))
320     return clib_error_return (0, "please specify valid device index");
321
322   if (thread_idx != (u32) ~ 0 && !(thread_idx < vec_len (dcm->workers_main)))
323     return clib_error_return (0, "invalid thread index");
324
325   dev = vec_elt_at_index (dcm->dev, dev_idx);
326   if (!(vec_len (dev->free_resources)))
327     return clib_error_return (0, "all device resources are being used");
328
329   /* Check thread is not already using the device */
330   /* *INDENT-OFF* */
331   vec_foreach (idx, dev->used_resources)
332     if (dcm->resource[idx[0]].thread_idx == thread_idx)
333       return clib_error_return (0, "thread %u already using device %u",
334                                 thread_idx, dev_idx);
335   /* *INDENT-ON* */
336
337   res_idx = vec_pop (dev->free_resources);
338   vec_add1 (dev->used_resources, res_idx);
339
340   cwm = vec_elt_at_index (dcm->workers_main, thread_idx);
341
342   ASSERT (dcm->resource[res_idx].thread_idx == (u16) ~ 0);
343   dcm->resource[res_idx].thread_idx = thread_idx;
344
345   /* Add device to vector of polling resources */
346   vec_add1 (cwm->resource_idx, res_idx);
347
348   /* Set device as default for all supported algos */
349   for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
350     if (dev->cipher_support[i])
351       {
352         if (cwm->cipher_resource_idx[i] == (u16) ~ 0)
353           dcm->cipher_algs[i].disabled--;
354         cwm->cipher_resource_idx[i] = res_idx;
355       }
356
357   for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
358     if (dev->auth_support[i])
359       {
360         if (cwm->auth_resource_idx[i] == (u16) ~ 0)
361           dcm->auth_algs[i].disabled--;
362         cwm->auth_resource_idx[i] = res_idx;
363       }
364
365   /* Check if any unused resource */
366
367   u8 used = 0;
368   /* *INDENT-OFF* */
369   vec_foreach (idx, cwm->resource_idx)
370     {
371       if (idx[0] == res_idx)
372         continue;
373
374       for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
375         used |= cwm->cipher_resource_idx[i] == idx[0];
376
377       for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
378         used |= cwm->auth_resource_idx[i] == idx[0];
379
380       vec_elt_at_index (dcm->resource, idx[0])->remove = !used;
381     }
382   /* *INDENT-ON* */
383
384   return 0;
385 }
386
387 /* *INDENT-OFF* */
388 VLIB_CLI_COMMAND (set_dpdk_crypto_placement, static) = {
389     .path = "set dpdk crypto placement",
390     .short_help = "set dpdk crypto placement (<device> <thread> | auto)",
391     .function = set_dpdk_crypto_placement_fn,
392 };
393 /* *INDENT-ON* */
394
395 /*
396  * The thread will not enqueue more operations to the device but will poll
397  * from it until there are no more inflight operations.
398 */
399 static void
400 dpdk_crypto_clear_resource (u16 res_idx)
401 {
402   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
403   crypto_resource_t *res = vec_elt_at_index (dcm->resource, res_idx);
404   crypto_worker_main_t *cwm = &dcm->workers_main[res->thread_idx];
405   u32 i;
406
407   for (i = 0; i < IPSEC_CRYPTO_N_ALG; i++)
408     if (cwm->cipher_resource_idx[i] == res_idx)
409       {
410         cwm->cipher_resource_idx[i] = (u16) ~ 0;
411         dcm->cipher_algs[i].disabled++;
412       }
413
414   for (i = 0; i < IPSEC_INTEG_N_ALG; i++)
415     if (cwm->auth_resource_idx[i] == res_idx)
416       {
417         cwm->auth_resource_idx[i] = (u16) ~ 0;
418         dcm->auth_algs[i].disabled++;
419       }
420
421   /* Fully remove device on crypto_node once there are no inflights */
422   res->remove = 1;
423 }
424
425 static clib_error_t *
426 clear_dpdk_crypto_placement_fn (vlib_main_t * vm,
427                                 unformat_input_t *
428                                 input, vlib_cli_command_t * cmd)
429 {
430   unformat_input_t _line_input, *line_input = &_line_input;
431   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
432   crypto_dev_t *dev;
433   u32 thread_idx = (u32) ~ 0;
434   u16 *res_idx;
435   u8 dev_idx = (u8) ~ 0;
436   u8 free_all = 0;
437
438   if (!unformat_user (input, unformat_line_input, line_input))
439     return clib_error_return (0, "invalid syntax");
440
441   while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
442     {
443       if (unformat (line_input, "%u %u", &dev_idx, &thread_idx))
444         ;
445       else if (unformat (line_input, "%u", &dev_idx))
446         free_all = 1;
447       else
448         {
449           unformat_free (line_input);
450           return clib_error_return (0, "parse error: '%U'",
451                                     format_unformat_error, line_input);
452         }
453     }
454
455   unformat_free (line_input);
456
457   if (!(dev_idx < vec_len (dcm->dev)))
458     return clib_error_return (0, "invalid device index");
459
460   dev = vec_elt_at_index (dcm->dev, dev_idx);
461
462   /* Clear all resources placements */
463   if (free_all)
464     {
465     /* *INDENT-OFF* */
466     vec_foreach (res_idx, dev->used_resources)
467       dpdk_crypto_clear_resource (res_idx[0]);
468     /* *INDENT-ON* */
469
470       return 0;
471     }
472
473   if (!(thread_idx < vec_len (dcm->workers_main)))
474     return clib_error_return (0, "invalid thread index");
475
476   /* Clear placement of device for given thread index */
477   /* *INDENT-OFF* */
478   vec_foreach (res_idx, dev->used_resources)
479     if (dcm->resource[res_idx[0]].thread_idx == thread_idx)
480       break;
481   /* *INDENT-ON* */
482
483   if (!(res_idx < vec_end (dev->used_resources)))
484     return clib_error_return (0, "thread %u is not using device %u",
485                               thread_idx, dev_idx);
486
487   dpdk_crypto_clear_resource (res_idx[0]);
488
489   return 0;
490 }
491
492 /* *INDENT-OFF* */
493 VLIB_CLI_COMMAND (clear_dpdk_crypto_placement, static) = {
494     .path = "clear dpdk crypto placement",
495     .short_help = "clear dpdk crypto placement <device> [<thread>]",
496     .function = clear_dpdk_crypto_placement_fn,
497 };
498 /* *INDENT-ON* */
499
500 u8 *
501 format_dpdk_mempool (u8 * s, va_list * args)
502 {
503   struct rte_mempool *mp = va_arg (*args, struct rte_mempool *);
504   u32 indent = format_get_indent (s);
505   u32 count = rte_mempool_avail_count (mp);
506
507   s = format (s, "%s\n%Uavailable %7d, allocated %7d total %7d\n",
508               mp->name, format_white_space, indent + 2,
509               count, mp->size - count, mp->size);
510   s = format (s, "%Uphys_addr %p, flags %08x, nb_mem_chunks %u\n",
511               format_white_space, indent + 2,
512               mp->mz->phys_addr, mp->flags, mp->nb_mem_chunks);
513   s = format (s, "%Uelt_size %4u, header_size %3u, trailer_size %u\n",
514               format_white_space, indent + 2,
515               mp->elt_size, mp->header_size, mp->trailer_size);
516   s = format (s, "%Uprivate_data_size %3u, total_elt_size %u\n",
517               format_white_space, indent + 2,
518               mp->private_data_size,
519               mp->elt_size + mp->header_size + mp->trailer_size);
520   return s;
521 }
522
523 static clib_error_t *
524 show_dpdk_crypto_pools_fn (vlib_main_t * vm,
525                            unformat_input_t * input, vlib_cli_command_t * cmd)
526 {
527   dpdk_crypto_main_t *dcm = &dpdk_crypto_main;
528   crypto_data_t *data;
529
530   /* *INDENT-OFF* */
531   vec_foreach (data, dcm->data)
532   {
533     if (data->crypto_op)
534       vlib_cli_output (vm, "%U\n", format_dpdk_mempool, data->crypto_op);
535     if (data->session_h)
536       vlib_cli_output (vm, "%U\n", format_dpdk_mempool, data->session_h);
537
538     struct rte_mempool **mp;
539     vec_foreach (mp, data->session_drv)
540       if (mp[0])
541         vlib_cli_output (vm, "%U\n", format_dpdk_mempool, mp[0]);
542   }
543   /* *INDENT-ON* */
544
545   return NULL;
546 }
547
548 /*?
549  * This command is used to display the DPDK Crypto pools information.
550  *
551  * @cliexpar
552  * Example of how to display the DPDK Crypto pools information:
553  * @cliexstart{show crypto device mapping}
554  * vpp# show dpdk crypto pools
555  * crypto_pool_numa1
556  * available   15872, allocated     512 total   16384
557  * phys_addr 0xf3d2086c0, flags 00000010, nb_mem_chunks 1
558  * elt_size  160, header_size  64, trailer_size 96
559  * private_data_size  64, total_elt_size 320
560  *
561  * session_h_pool_numa1
562  * available   19998, allocated       2 total   20000
563  * phys_addr 0xf3c9c4380, flags 00000010, nb_mem_chunks 1
564  * elt_size   40, header_size  64, trailer_size 88
565  * private_data_size   0, total_elt_size 192
566  *
567  * session_drv0_pool_numa1
568  * available   19998, allocated       2 total   20000
569  * phys_addr 0xf3ad42d80, flags 00000010, nb_mem_chunks 1
570  * elt_size  512, header_size  64, trailer_size 0
571  * private_data_size   0, total_elt_size 576
572  * @cliexend
573 ?*/
574 /* *INDENT-OFF* */
575 VLIB_CLI_COMMAND (show_dpdk_crypto_pools, static) = {
576     .path = "show dpdk crypto pools",
577     .short_help = "show dpdk crypto pools",
578     .function = show_dpdk_crypto_pools_fn,
579 };
580 /* *INDENT-ON* */
581
582 /* TODO Allow user define number of sessions supported */
583 /* TODO Allow user define descriptor queue size */
584
585 /*
586  * fd.io coding-style-patch-verification: ON
587  *
588  * Local Variables:
589  * eval: (c-set-style "gnu")
590  * End:
591  */