]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/dpdk/examples/ip_pipeline/cli.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / dpdk / examples / ip_pipeline / cli.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
3 */
4
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include <rte_common.h>
11 #include <rte_cycles.h>
12 #include <rte_ethdev.h>
13
14 #include "cli.h"
15
16 #include "cryptodev.h"
17 #include "kni.h"
18 #include "link.h"
19 #include "mempool.h"
20 #include "parser.h"
21 #include "pipeline.h"
22 #include "swq.h"
23 #include "tap.h"
24 #include "thread.h"
25 #include "tmgr.h"
26
27 #ifndef CMD_MAX_TOKENS
28 #define CMD_MAX_TOKENS 256
29 #endif
30
31 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
32 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
33 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
34 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
35 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
36 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
37 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
38 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
39 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
40 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
41 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
42
43 static int
44 is_comment(char *in)
45 {
46 if ((strlen(in) && index("!#%;", in[0])) ||
47 (strncmp(in, "//", 2) == 0) ||
48 (strncmp(in, "--", 2) == 0))
49 return 1;
50
51 return 0;
52 }
53
54 static const char cmd_mempool_help[] =
55 "mempool <mempool_name>\n"
56 " buffer <buffer_size>\n"
57 " pool <pool_size>\n"
58 " cache <cache_size>\n"
59 " cpu <cpu_id>\n";
60
61 static void
62 cmd_mempool(char **tokens,
63 uint32_t n_tokens,
64 char *out,
65 size_t out_size)
66 {
67 struct mempool_params p;
68 char *name;
69 struct mempool *mempool;
70
71 if (n_tokens != 10) {
72 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
73 return;
74 }
75
76 name = tokens[1];
77
78 if (strcmp(tokens[2], "buffer") != 0) {
79 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
80 return;
81 }
82
83 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
84 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
85 return;
86 }
87
88 if (strcmp(tokens[4], "pool") != 0) {
89 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
90 return;
91 }
92
93 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
94 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
95 return;
96 }
97
98 if (strcmp(tokens[6], "cache") != 0) {
99 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
100 return;
101 }
102
103 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
104 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
105 return;
106 }
107
108 if (strcmp(tokens[8], "cpu") != 0) {
109 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
110 return;
111 }
112
113 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
114 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
115 return;
116 }
117
118 mempool = mempool_create(name, &p);
119 if (mempool == NULL) {
120 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
121 return;
122 }
123 }
124
125 static const char cmd_link_help[] =
126 "link <link_name>\n"
127 " dev <device_name> | port <port_id>\n"
128 " rxq <n_queues> <queue_size> <mempool_name>\n"
129 " txq <n_queues> <queue_size>\n"
130 " promiscuous on | off\n"
131 " [rss <qid_0> ... <qid_n>]\n";
132
133 static void
134 cmd_link(char **tokens,
135 uint32_t n_tokens,
136 char *out,
137 size_t out_size)
138 {
139 struct link_params p;
140 struct link_params_rss rss;
141 struct link *link;
142 char *name;
143
144 memset(&p, 0, sizeof(p));
145
146 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
147 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
148 return;
149 }
150 name = tokens[1];
151
152 if (strcmp(tokens[2], "dev") == 0)
153 p.dev_name = tokens[3];
154 else if (strcmp(tokens[2], "port") == 0) {
155 p.dev_name = NULL;
156
157 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
158 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
159 return;
160 }
161 } else {
162 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
163 return;
164 }
165
166 if (strcmp(tokens[4], "rxq") != 0) {
167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
168 return;
169 }
170
171 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
172 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
173 return;
174 }
175 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
176 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
177 return;
178 }
179
180 p.rx.mempool_name = tokens[7];
181
182 if (strcmp(tokens[8], "txq") != 0) {
183 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
184 return;
185 }
186
187 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
188 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
189 return;
190 }
191
192 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
193 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
194 return;
195 }
196
197 if (strcmp(tokens[11], "promiscuous") != 0) {
198 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
199 return;
200 }
201
202 if (strcmp(tokens[12], "on") == 0)
203 p.promiscuous = 1;
204 else if (strcmp(tokens[12], "off") == 0)
205 p.promiscuous = 0;
206 else {
207 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
208 return;
209 }
210
211 /* RSS */
212 p.rx.rss = NULL;
213 if (n_tokens > 13) {
214 uint32_t queue_id, i;
215
216 if (strcmp(tokens[13], "rss") != 0) {
217 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
218 return;
219 }
220
221 p.rx.rss = &rss;
222
223 rss.n_queues = 0;
224 for (i = 14; i < n_tokens; i++) {
225 if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
226 snprintf(out, out_size, MSG_ARG_INVALID,
227 "queue_id");
228 return;
229 }
230
231 rss.queue_id[rss.n_queues] = queue_id;
232 rss.n_queues++;
233 }
234 }
235
236 link = link_create(name, &p);
237 if (link == NULL) {
238 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
239 return;
240 }
241 }
242
243 /* Print the link stats and info */
244 static void
245 print_link_info(struct link *link, char *out, size_t out_size)
246 {
247 struct rte_eth_stats stats;
248 struct rte_ether_addr mac_addr;
249 struct rte_eth_link eth_link;
250 uint16_t mtu;
251 int ret;
252
253 memset(&stats, 0, sizeof(stats));
254 rte_eth_stats_get(link->port_id, &stats);
255
256 ret = rte_eth_macaddr_get(link->port_id, &mac_addr);
257 if (ret != 0) {
258 snprintf(out, out_size, "\n%s: MAC address get failed: %s",
259 link->name, rte_strerror(-ret));
260 return;
261 }
262
263 ret = rte_eth_link_get(link->port_id, &eth_link);
264 if (ret < 0) {
265 snprintf(out, out_size, "\n%s: link get failed: %s",
266 link->name, rte_strerror(-ret));
267 return;
268 }
269
270 rte_eth_dev_get_mtu(link->port_id, &mtu);
271
272 snprintf(out, out_size,
273 "\n"
274 "%s: flags=<%s> mtu %u\n"
275 "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n"
276 "\tport# %u speed %u Mbps\n"
277 "\tRX packets %" PRIu64" bytes %" PRIu64"\n"
278 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
279 "\tTX packets %" PRIu64" bytes %" PRIu64"\n"
280 "\tTX errors %" PRIu64"\n",
281 link->name,
282 eth_link.link_status == 0 ? "DOWN" : "UP",
283 mtu,
284 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
285 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
286 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5],
287 link->n_rxq,
288 link->n_txq,
289 link->port_id,
290 eth_link.link_speed,
291 stats.ipackets,
292 stats.ibytes,
293 stats.ierrors,
294 stats.imissed,
295 stats.rx_nombuf,
296 stats.opackets,
297 stats.obytes,
298 stats.oerrors);
299 }
300
301 /*
302 * link show [<link_name>]
303 */
304 static void
305 cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size)
306 {
307 struct link *link;
308 char *link_name;
309
310 if (n_tokens != 2 && n_tokens != 3) {
311 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
312 return;
313 }
314
315 if (n_tokens == 2) {
316 link = link_next(NULL);
317
318 while (link != NULL) {
319 out_size = out_size - strlen(out);
320 out = &out[strlen(out)];
321
322 print_link_info(link, out, out_size);
323 link = link_next(link);
324 }
325 } else {
326 out_size = out_size - strlen(out);
327 out = &out[strlen(out)];
328
329 link_name = tokens[2];
330 link = link_find(link_name);
331
332 if (link == NULL) {
333 snprintf(out, out_size, MSG_ARG_INVALID,
334 "Link does not exist");
335 return;
336 }
337 print_link_info(link, out, out_size);
338 }
339 }
340
341 static const char cmd_swq_help[] =
342 "swq <swq_name>\n"
343 " size <size>\n"
344 " cpu <cpu_id>\n";
345
346 static void
347 cmd_swq(char **tokens,
348 uint32_t n_tokens,
349 char *out,
350 size_t out_size)
351 {
352 struct swq_params p;
353 char *name;
354 struct swq *swq;
355
356 if (n_tokens != 6) {
357 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
358 return;
359 }
360
361 name = tokens[1];
362
363 if (strcmp(tokens[2], "size") != 0) {
364 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
365 return;
366 }
367
368 if (parser_read_uint32(&p.size, tokens[3]) != 0) {
369 snprintf(out, out_size, MSG_ARG_INVALID, "size");
370 return;
371 }
372
373 if (strcmp(tokens[4], "cpu") != 0) {
374 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
375 return;
376 }
377
378 if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) {
379 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
380 return;
381 }
382
383 swq = swq_create(name, &p);
384 if (swq == NULL) {
385 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
386 return;
387 }
388 }
389
390 static const char cmd_tmgr_subport_profile_help[] =
391 "tmgr subport profile\n"
392 " <tb_rate> <tb_size>\n"
393 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>"
394 " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>"
395 " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n"
396 " <tc_period>\n"
397 " pps <n_pipes_per_subport>\n"
398 " qsize <qsize_tc0> <qsize_tc1> <qsize_tc2>"
399 " <qsize_tc3> <qsize_tc4> <qsize_tc5> <qsize_tc6>"
400 " <qsize_tc7> <qsize_tc8> <qsize_tc9> <qsize_tc10>"
401 " <qsize_tc11> <qsize_tc12>";
402
403 static void
404 cmd_tmgr_subport_profile(char **tokens,
405 uint32_t n_tokens,
406 char *out,
407 size_t out_size)
408 {
409 struct rte_sched_subport_params p;
410 int status, i;
411
412 if (n_tokens != 35) {
413 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
414 return;
415 }
416
417 if (parser_read_uint64(&p.tb_rate, tokens[3]) != 0) {
418 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
419 return;
420 }
421
422 if (parser_read_uint64(&p.tb_size, tokens[4]) != 0) {
423 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
424 return;
425 }
426
427 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
428 if (parser_read_uint64(&p.tc_rate[i], tokens[5 + i]) != 0) {
429 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
430 return;
431 }
432
433 if (parser_read_uint64(&p.tc_period, tokens[18]) != 0) {
434 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
435 return;
436 }
437
438 if (strcmp(tokens[19], "pps") != 0) {
439 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
440 return;
441 }
442
443 if (parser_read_uint32(&p.n_pipes_per_subport_enabled, tokens[20]) != 0) {
444 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
445 return;
446 }
447
448 if (strcmp(tokens[21], "qsize") != 0) {
449 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize");
450 return;
451 }
452
453 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
454 if (parser_read_uint16(&p.qsize[i], tokens[22 + i]) != 0) {
455 snprintf(out, out_size, MSG_ARG_INVALID, "qsize");
456 return;
457 }
458
459 status = tmgr_subport_profile_add(&p);
460 if (status != 0) {
461 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
462 return;
463 }
464 }
465
466 static const char cmd_tmgr_pipe_profile_help[] =
467 "tmgr pipe profile\n"
468 " <tb_rate> <tb_size>\n"
469 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> <tc4_rate>"
470 " <tc5_rate> <tc6_rate> <tc7_rate> <tc8_rate>"
471 " <tc9_rate> <tc10_rate> <tc11_rate> <tc12_rate>\n"
472 " <tc_period>\n"
473 " <tc_ov_weight>\n"
474 " <wrr_weight0..3>\n";
475
476 static void
477 cmd_tmgr_pipe_profile(char **tokens,
478 uint32_t n_tokens,
479 char *out,
480 size_t out_size)
481 {
482 struct rte_sched_pipe_params p;
483 int status, i;
484
485 if (n_tokens != 24) {
486 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
487 return;
488 }
489
490 if (parser_read_uint64(&p.tb_rate, tokens[3]) != 0) {
491 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
492 return;
493 }
494
495 if (parser_read_uint64(&p.tb_size, tokens[4]) != 0) {
496 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
497 return;
498 }
499
500 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
501 if (parser_read_uint64(&p.tc_rate[i], tokens[5 + i]) != 0) {
502 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
503 return;
504 }
505
506 if (parser_read_uint64(&p.tc_period, tokens[18]) != 0) {
507 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
508 return;
509 }
510
511 if (parser_read_uint8(&p.tc_ov_weight, tokens[19]) != 0) {
512 snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight");
513 return;
514 }
515
516 for (i = 0; i < RTE_SCHED_BE_QUEUES_PER_PIPE; i++)
517 if (parser_read_uint8(&p.wrr_weights[i], tokens[20 + i]) != 0) {
518 snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights");
519 return;
520 }
521
522 status = tmgr_pipe_profile_add(&p);
523 if (status != 0) {
524 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
525 return;
526 }
527 }
528
529 static const char cmd_tmgr_help[] =
530 "tmgr <tmgr_name>\n"
531 " rate <rate>\n"
532 " spp <n_subports_per_port>\n"
533 " fo <frame_overhead>\n"
534 " mtu <mtu>\n"
535 " cpu <cpu_id>\n";
536
537 static void
538 cmd_tmgr(char **tokens,
539 uint32_t n_tokens,
540 char *out,
541 size_t out_size)
542 {
543 struct tmgr_port_params p;
544 char *name;
545 struct tmgr_port *tmgr_port;
546
547 if (n_tokens != 12) {
548 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
549 return;
550 }
551
552 name = tokens[1];
553
554 if (strcmp(tokens[2], "rate") != 0) {
555 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
556 return;
557 }
558
559 if (parser_read_uint64(&p.rate, tokens[3]) != 0) {
560 snprintf(out, out_size, MSG_ARG_INVALID, "rate");
561 return;
562 }
563
564 if (strcmp(tokens[4], "spp") != 0) {
565 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
566 return;
567 }
568
569 if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) {
570 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
571 return;
572 }
573
574 if (strcmp(tokens[6], "fo") != 0) {
575 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo");
576 return;
577 }
578
579 if (parser_read_uint32(&p.frame_overhead, tokens[7]) != 0) {
580 snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead");
581 return;
582 }
583
584 if (strcmp(tokens[8], "mtu") != 0) {
585 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu");
586 return;
587 }
588
589 if (parser_read_uint32(&p.mtu, tokens[9]) != 0) {
590 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
591 return;
592 }
593
594 if (strcmp(tokens[10], "cpu") != 0) {
595 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
596 return;
597 }
598
599 if (parser_read_uint32(&p.cpu_id, tokens[11]) != 0) {
600 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
601 return;
602 }
603
604 tmgr_port = tmgr_port_create(name, &p);
605 if (tmgr_port == NULL) {
606 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
607 return;
608 }
609 }
610
611 static const char cmd_tmgr_subport_help[] =
612 "tmgr <tmgr_name> subport <subport_id>\n"
613 " profile <subport_profile_id>\n";
614
615 static void
616 cmd_tmgr_subport(char **tokens,
617 uint32_t n_tokens,
618 char *out,
619 size_t out_size)
620 {
621 uint32_t subport_id, subport_profile_id;
622 int status;
623 char *name;
624
625 if (n_tokens != 6) {
626 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
627 return;
628 }
629
630 name = tokens[1];
631
632 if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
633 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
634 return;
635 }
636
637 if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) {
638 snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id");
639 return;
640 }
641
642 status = tmgr_subport_config(name, subport_id, subport_profile_id);
643 if (status) {
644 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
645 return;
646 }
647 }
648
649
650 static const char cmd_tmgr_subport_pipe_help[] =
651 "tmgr <tmgr_name> subport <subport_id> pipe\n"
652 " from <pipe_id_first> to <pipe_id_last>\n"
653 " profile <pipe_profile_id>\n";
654
655 static void
656 cmd_tmgr_subport_pipe(char **tokens,
657 uint32_t n_tokens,
658 char *out,
659 size_t out_size)
660 {
661 uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id;
662 int status;
663 char *name;
664
665 if (n_tokens != 11) {
666 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
667 return;
668 }
669
670 name = tokens[1];
671
672 if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
673 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
674 return;
675 }
676
677 if (strcmp(tokens[4], "pipe") != 0) {
678 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
679 return;
680 }
681
682 if (strcmp(tokens[5], "from") != 0) {
683 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
684 return;
685 }
686
687 if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) {
688 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first");
689 return;
690 }
691
692 if (strcmp(tokens[7], "to") != 0) {
693 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
694 return;
695 }
696
697 if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) {
698 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last");
699 return;
700 }
701
702 if (strcmp(tokens[9], "profile") != 0) {
703 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
704 return;
705 }
706
707 if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) {
708 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
709 return;
710 }
711
712 status = tmgr_pipe_config(name, subport_id, pipe_id_first,
713 pipe_id_last, pipe_profile_id);
714 if (status) {
715 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
716 return;
717 }
718 }
719
720
721 static const char cmd_tap_help[] =
722 "tap <tap_name>\n";
723
724 static void
725 cmd_tap(char **tokens,
726 uint32_t n_tokens,
727 char *out,
728 size_t out_size)
729 {
730 char *name;
731 struct tap *tap;
732
733 if (n_tokens != 2) {
734 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
735 return;
736 }
737
738 name = tokens[1];
739
740 tap = tap_create(name);
741 if (tap == NULL) {
742 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
743 return;
744 }
745 }
746
747 static const char cmd_kni_help[] =
748 "kni <kni_name>\n"
749 " link <link_name>\n"
750 " mempool <mempool_name>\n"
751 " [thread <thread_id>]\n";
752
753 static void
754 cmd_kni(char **tokens,
755 uint32_t n_tokens,
756 char *out,
757 size_t out_size)
758 {
759 struct kni_params p;
760 char *name;
761 struct kni *kni;
762
763 memset(&p, 0, sizeof(p));
764 if ((n_tokens != 6) && (n_tokens != 8)) {
765 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
766 return;
767 }
768
769 name = tokens[1];
770
771 if (strcmp(tokens[2], "link") != 0) {
772 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link");
773 return;
774 }
775
776 p.link_name = tokens[3];
777
778 if (strcmp(tokens[4], "mempool") != 0) {
779 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool");
780 return;
781 }
782
783 p.mempool_name = tokens[5];
784
785 if (n_tokens == 8) {
786 if (strcmp(tokens[6], "thread") != 0) {
787 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread");
788 return;
789 }
790
791 if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) {
792 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
793 return;
794 }
795
796 p.force_bind = 1;
797 } else
798 p.force_bind = 0;
799
800 kni = kni_create(name, &p);
801 if (kni == NULL) {
802 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
803 return;
804 }
805 }
806
807 static const char cmd_cryptodev_help[] =
808 "cryptodev <cryptodev_name>\n"
809 " dev <device_name> | dev_id <device_id>\n"
810 " queue <n_queues> <queue_size>\n"
811 " max_sessions <n_sessions>";
812
813 static void
814 cmd_cryptodev(char **tokens,
815 uint32_t n_tokens,
816 char *out,
817 size_t out_size)
818 {
819 struct cryptodev_params params;
820 char *name;
821
822 memset(&params, 0, sizeof(params));
823 if (n_tokens != 9) {
824 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
825 return;
826 }
827
828 name = tokens[1];
829
830 if (strcmp(tokens[2], "dev") == 0)
831 params.dev_name = tokens[3];
832 else if (strcmp(tokens[2], "dev_id") == 0) {
833 if (parser_read_uint32(&params.dev_id, tokens[3]) < 0) {
834 snprintf(out, out_size, MSG_ARG_INVALID,
835 "dev_id");
836 return;
837 }
838 } else {
839 snprintf(out, out_size, MSG_ARG_INVALID,
840 "cryptodev");
841 return;
842 }
843
844 if (strcmp(tokens[4], "queue")) {
845 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
846 "queue");
847 return;
848 }
849
850 if (parser_read_uint32(&params.n_queues, tokens[5]) < 0) {
851 snprintf(out, out_size, MSG_ARG_INVALID,
852 "q");
853 return;
854 }
855
856 if (parser_read_uint32(&params.queue_size, tokens[6]) < 0) {
857 snprintf(out, out_size, MSG_ARG_INVALID,
858 "queue_size");
859 return;
860 }
861
862 if (strcmp(tokens[7], "max_sessions")) {
863 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
864 "max_sessions");
865 return;
866 }
867
868 if (parser_read_uint32(&params.session_pool_size, tokens[8]) < 0) {
869 snprintf(out, out_size, MSG_ARG_INVALID,
870 "queue_size");
871 return;
872 }
873
874 if (cryptodev_create(name, &params) == NULL) {
875 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
876 return;
877 }
878 }
879
880 static const char cmd_port_in_action_profile_help[] =
881 "port in action profile <profile_name>\n"
882 " [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n"
883 " [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\n";
884
885 static void
886 cmd_port_in_action_profile(char **tokens,
887 uint32_t n_tokens,
888 char *out,
889 size_t out_size)
890 {
891 struct port_in_action_profile_params p;
892 struct port_in_action_profile *ap;
893 char *name;
894 uint32_t t0;
895
896 memset(&p, 0, sizeof(p));
897
898 if (n_tokens < 5) {
899 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
900 return;
901 }
902
903 if (strcmp(tokens[1], "in") != 0) {
904 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
905 return;
906 }
907
908 if (strcmp(tokens[2], "action") != 0) {
909 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
910 return;
911 }
912
913 if (strcmp(tokens[3], "profile") != 0) {
914 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
915 return;
916 }
917
918 name = tokens[4];
919
920 t0 = 5;
921
922 if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) {
923 uint32_t size;
924
925 if (n_tokens < t0 + 10) {
926 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
927 return;
928 }
929
930 if (strcmp(tokens[t0 + 1], "match") == 0)
931 p.fltr.filter_on_match = 1;
932 else if (strcmp(tokens[t0 + 1], "mismatch") == 0)
933 p.fltr.filter_on_match = 0;
934 else {
935 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
936 return;
937 }
938
939 if (strcmp(tokens[t0 + 2], "offset") != 0) {
940 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
941 return;
942 }
943
944 if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) {
945 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
946 return;
947 }
948
949 if (strcmp(tokens[t0 + 4], "mask") != 0) {
950 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
951 return;
952 }
953
954 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
955 if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) ||
956 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
957 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
958 return;
959 }
960
961 if (strcmp(tokens[t0 + 6], "key") != 0) {
962 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
963 return;
964 }
965
966 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
967 if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) ||
968 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
969 snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
970 return;
971 }
972
973 if (strcmp(tokens[t0 + 8], "port") != 0) {
974 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
975 return;
976 }
977
978 if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) {
979 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
980 return;
981 }
982
983 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
984 t0 += 10;
985 } /* filter */
986
987 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) {
988 uint32_t i;
989
990 if (n_tokens < t0 + 22) {
991 snprintf(out, out_size, MSG_ARG_MISMATCH,
992 "port in action profile balance");
993 return;
994 }
995
996 if (strcmp(tokens[t0 + 1], "offset") != 0) {
997 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
998 return;
999 }
1000
1001 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) {
1002 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1003 return;
1004 }
1005
1006 if (strcmp(tokens[t0 + 3], "mask") != 0) {
1007 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1008 return;
1009 }
1010
1011 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
1012 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) {
1013 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1014 return;
1015 }
1016
1017 if (strcmp(tokens[t0 + 5], "port") != 0) {
1018 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1019 return;
1020 }
1021
1022 for (i = 0; i < 16; i++)
1023 if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) {
1024 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
1025 return;
1026 }
1027
1028 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
1029 t0 += 22;
1030 } /* balance */
1031
1032 if (t0 < n_tokens) {
1033 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1034 return;
1035 }
1036
1037 ap = port_in_action_profile_create(name, &p);
1038 if (ap == NULL) {
1039 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1040 return;
1041 }
1042 }
1043
1044
1045 static const char cmd_table_action_profile_help[] =
1046 "table action profile <profile_name>\n"
1047 " ipv4 | ipv6\n"
1048 " offset <ip_offset>\n"
1049 " fwd\n"
1050 " [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n"
1051 " [meter srtcm | trtcm\n"
1052 " tc <n_tc>\n"
1053 " stats none | pkts | bytes | both]\n"
1054 " [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\n"
1055 " [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe \n"
1056 " vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]\n"
1057 " [nat src | dst\n"
1058 " proto udp | tcp]\n"
1059 " [ttl drop | fwd\n"
1060 " stats none | pkts]\n"
1061 " [stats pkts | bytes | both]\n"
1062 " [time]\n"
1063 " [sym_crypto dev <CRYPTODEV_NAME> offset <op_offset>]\n"
1064 " [tag]\n"
1065 " [decap]\n";
1066
1067 static void
1068 cmd_table_action_profile(char **tokens,
1069 uint32_t n_tokens,
1070 char *out,
1071 size_t out_size)
1072 {
1073 struct table_action_profile_params p;
1074 struct table_action_profile *ap;
1075 char *name;
1076 uint32_t t0;
1077
1078 memset(&p, 0, sizeof(p));
1079
1080 if (n_tokens < 8) {
1081 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1082 return;
1083 }
1084
1085 if (strcmp(tokens[1], "action") != 0) {
1086 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
1087 return;
1088 }
1089
1090 if (strcmp(tokens[2], "profile") != 0) {
1091 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
1092 return;
1093 }
1094
1095 name = tokens[3];
1096
1097 if (strcmp(tokens[4], "ipv4") == 0)
1098 p.common.ip_version = 1;
1099 else if (strcmp(tokens[4], "ipv6") == 0)
1100 p.common.ip_version = 0;
1101 else {
1102 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
1103 return;
1104 }
1105
1106 if (strcmp(tokens[5], "offset") != 0) {
1107 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1108 return;
1109 }
1110
1111 if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) {
1112 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
1113 return;
1114 }
1115
1116 if (strcmp(tokens[7], "fwd") != 0) {
1117 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
1118 return;
1119 }
1120
1121 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
1122
1123 t0 = 8;
1124 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) {
1125 if (n_tokens < t0 + 7) {
1126 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
1127 return;
1128 }
1129
1130 if (strcmp(tokens[t0 + 1], "offset") != 0) {
1131 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1132 return;
1133 }
1134
1135 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) {
1136 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1137 return;
1138 }
1139
1140 if (strcmp(tokens[t0 + 3], "mask") != 0) {
1141 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1142 return;
1143 }
1144
1145 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
1146 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) {
1147 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1148 return;
1149 }
1150
1151 if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
1152 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
1153 return;
1154 }
1155
1156 if (parser_read_uint32(&p.lb.out_offset, tokens[t0 + 6]) != 0) {
1157 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
1158 return;
1159 }
1160
1161 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
1162 t0 += 7;
1163 } /* balance */
1164
1165 if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) {
1166 if (n_tokens < t0 + 6) {
1167 snprintf(out, out_size, MSG_ARG_MISMATCH,
1168 "table action profile meter");
1169 return;
1170 }
1171
1172 if (strcmp(tokens[t0 + 1], "srtcm") == 0)
1173 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
1174 else if (strcmp(tokens[t0 + 1], "trtcm") == 0)
1175 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
1176 else {
1177 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1178 "srtcm or trtcm");
1179 return;
1180 }
1181
1182 if (strcmp(tokens[t0 + 2], "tc") != 0) {
1183 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
1184 return;
1185 }
1186
1187 if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) {
1188 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
1189 return;
1190 }
1191
1192 if (strcmp(tokens[t0 + 4], "stats") != 0) {
1193 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1194 return;
1195 }
1196
1197 if (strcmp(tokens[t0 + 5], "none") == 0) {
1198 p.mtr.n_packets_enabled = 0;
1199 p.mtr.n_bytes_enabled = 0;
1200 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
1201 p.mtr.n_packets_enabled = 1;
1202 p.mtr.n_bytes_enabled = 0;
1203 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
1204 p.mtr.n_packets_enabled = 0;
1205 p.mtr.n_bytes_enabled = 1;
1206 } else if (strcmp(tokens[t0 + 5], "both") == 0) {
1207 p.mtr.n_packets_enabled = 1;
1208 p.mtr.n_bytes_enabled = 1;
1209 } else {
1210 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1211 "none or pkts or bytes or both");
1212 return;
1213 }
1214
1215 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
1216 t0 += 6;
1217 } /* meter */
1218
1219 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) {
1220 if (n_tokens < t0 + 5) {
1221 snprintf(out, out_size, MSG_ARG_MISMATCH,
1222 "table action profile tm");
1223 return;
1224 }
1225
1226 if (strcmp(tokens[t0 + 1], "spp") != 0) {
1227 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
1228 return;
1229 }
1230
1231 if (parser_read_uint32(&p.tm.n_subports_per_port,
1232 tokens[t0 + 2]) != 0) {
1233 snprintf(out, out_size, MSG_ARG_INVALID,
1234 "n_subports_per_port");
1235 return;
1236 }
1237
1238 if (strcmp(tokens[t0 + 3], "pps") != 0) {
1239 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
1240 return;
1241 }
1242
1243 if (parser_read_uint32(&p.tm.n_pipes_per_subport,
1244 tokens[t0 + 4]) != 0) {
1245 snprintf(out, out_size, MSG_ARG_INVALID,
1246 "n_pipes_per_subport");
1247 return;
1248 }
1249
1250 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
1251 t0 += 5;
1252 } /* tm */
1253
1254 if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) {
1255 uint32_t n_extra_tokens = 0;
1256
1257 if (n_tokens < t0 + 2) {
1258 snprintf(out, out_size, MSG_ARG_MISMATCH,
1259 "action profile encap");
1260 return;
1261 }
1262
1263 if (strcmp(tokens[t0 + 1], "ether") == 0)
1264 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
1265 else if (strcmp(tokens[t0 + 1], "vlan") == 0)
1266 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
1267 else if (strcmp(tokens[t0 + 1], "qinq") == 0)
1268 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
1269 else if (strcmp(tokens[t0 + 1], "mpls") == 0)
1270 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
1271 else if (strcmp(tokens[t0 + 1], "pppoe") == 0)
1272 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
1273 else if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
1274 if (n_tokens < t0 + 2 + 5) {
1275 snprintf(out, out_size, MSG_ARG_MISMATCH,
1276 "action profile encap vxlan");
1277 return;
1278 }
1279
1280 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1281 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1282 "vxlan: offset");
1283 return;
1284 }
1285
1286 if (parser_read_uint32(&p.encap.vxlan.data_offset,
1287 tokens[t0 + 2 + 1]) != 0) {
1288 snprintf(out, out_size, MSG_ARG_INVALID,
1289 "vxlan: ether_offset");
1290 return;
1291 }
1292
1293 if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
1294 p.encap.vxlan.ip_version = 1;
1295 else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
1296 p.encap.vxlan.ip_version = 0;
1297 else {
1298 snprintf(out, out_size, MSG_ARG_INVALID,
1299 "vxlan: ipv4 or ipv6");
1300 return;
1301 }
1302
1303 if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
1304 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1305 "vxlan: vlan");
1306 return;
1307 }
1308
1309 if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
1310 p.encap.vxlan.vlan = 1;
1311 else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
1312 p.encap.vxlan.vlan = 0;
1313 else {
1314 snprintf(out, out_size, MSG_ARG_INVALID,
1315 "vxlan: on or off");
1316 return;
1317 }
1318
1319 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
1320 n_extra_tokens = 5;
1321 } else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0)
1322 p.encap.encap_mask =
1323 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
1324 else {
1325 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
1326 return;
1327 }
1328
1329 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
1330 t0 += 2 + n_extra_tokens;
1331 } /* encap */
1332
1333 if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) {
1334 if (n_tokens < t0 + 4) {
1335 snprintf(out, out_size, MSG_ARG_MISMATCH,
1336 "table action profile nat");
1337 return;
1338 }
1339
1340 if (strcmp(tokens[t0 + 1], "src") == 0)
1341 p.nat.source_nat = 1;
1342 else if (strcmp(tokens[t0 + 1], "dst") == 0)
1343 p.nat.source_nat = 0;
1344 else {
1345 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1346 "src or dst");
1347 return;
1348 }
1349
1350 if (strcmp(tokens[t0 + 2], "proto") != 0) {
1351 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
1352 return;
1353 }
1354
1355 if (strcmp(tokens[t0 + 3], "tcp") == 0)
1356 p.nat.proto = 0x06;
1357 else if (strcmp(tokens[t0 + 3], "udp") == 0)
1358 p.nat.proto = 0x11;
1359 else {
1360 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1361 "tcp or udp");
1362 return;
1363 }
1364
1365 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
1366 t0 += 4;
1367 } /* nat */
1368
1369 if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) {
1370 if (n_tokens < t0 + 4) {
1371 snprintf(out, out_size, MSG_ARG_MISMATCH,
1372 "table action profile ttl");
1373 return;
1374 }
1375
1376 if (strcmp(tokens[t0 + 1], "drop") == 0)
1377 p.ttl.drop = 1;
1378 else if (strcmp(tokens[t0 + 1], "fwd") == 0)
1379 p.ttl.drop = 0;
1380 else {
1381 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1382 "drop or fwd");
1383 return;
1384 }
1385
1386 if (strcmp(tokens[t0 + 2], "stats") != 0) {
1387 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1388 return;
1389 }
1390
1391 if (strcmp(tokens[t0 + 3], "none") == 0)
1392 p.ttl.n_packets_enabled = 0;
1393 else if (strcmp(tokens[t0 + 3], "pkts") == 0)
1394 p.ttl.n_packets_enabled = 1;
1395 else {
1396 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1397 "none or pkts");
1398 return;
1399 }
1400
1401 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
1402 t0 += 4;
1403 } /* ttl */
1404
1405 if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) {
1406 if (n_tokens < t0 + 2) {
1407 snprintf(out, out_size, MSG_ARG_MISMATCH,
1408 "table action profile stats");
1409 return;
1410 }
1411
1412 if (strcmp(tokens[t0 + 1], "pkts") == 0) {
1413 p.stats.n_packets_enabled = 1;
1414 p.stats.n_bytes_enabled = 0;
1415 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
1416 p.stats.n_packets_enabled = 0;
1417 p.stats.n_bytes_enabled = 1;
1418 } else if (strcmp(tokens[t0 + 1], "both") == 0) {
1419 p.stats.n_packets_enabled = 1;
1420 p.stats.n_bytes_enabled = 1;
1421 } else {
1422 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1423 "pkts or bytes or both");
1424 return;
1425 }
1426
1427 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
1428 t0 += 2;
1429 } /* stats */
1430
1431 if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) {
1432 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
1433 t0 += 1;
1434 } /* time */
1435
1436 if ((t0 < n_tokens) && (strcmp(tokens[t0], "sym_crypto") == 0)) {
1437 struct cryptodev *cryptodev;
1438
1439 if (n_tokens < t0 + 5 ||
1440 strcmp(tokens[t0 + 1], "dev") ||
1441 strcmp(tokens[t0 + 3], "offset")) {
1442 snprintf(out, out_size, MSG_ARG_MISMATCH,
1443 "table action profile sym_crypto");
1444 return;
1445 }
1446
1447 cryptodev = cryptodev_find(tokens[t0 + 2]);
1448 if (cryptodev == NULL) {
1449 snprintf(out, out_size, MSG_ARG_INVALID,
1450 "table action profile sym_crypto");
1451 return;
1452 }
1453
1454 p.sym_crypto.cryptodev_id = cryptodev->dev_id;
1455
1456 if (parser_read_uint32(&p.sym_crypto.op_offset,
1457 tokens[t0 + 4]) != 0) {
1458 snprintf(out, out_size, MSG_ARG_INVALID,
1459 "table action profile sym_crypto");
1460 return;
1461 }
1462
1463 p.sym_crypto.mp_create = cryptodev->mp_create;
1464 p.sym_crypto.mp_init = cryptodev->mp_init;
1465
1466 p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO;
1467
1468 t0 += 5;
1469 } /* sym_crypto */
1470
1471 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tag") == 0)) {
1472 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG;
1473 t0 += 1;
1474 } /* tag */
1475
1476 if ((t0 < n_tokens) && (strcmp(tokens[t0], "decap") == 0)) {
1477 p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP;
1478 t0 += 1;
1479 } /* decap */
1480
1481 if (t0 < n_tokens) {
1482 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1483 return;
1484 }
1485
1486 ap = table_action_profile_create(name, &p);
1487 if (ap == NULL) {
1488 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1489 return;
1490 }
1491 }
1492
1493 static const char cmd_pipeline_help[] =
1494 "pipeline <pipeline_name>\n"
1495 " period <timer_period_ms>\n"
1496 " offset_port_id <offset_port_id>\n"
1497 " cpu <cpu_id>\n";
1498
1499 static void
1500 cmd_pipeline(char **tokens,
1501 uint32_t n_tokens,
1502 char *out,
1503 size_t out_size)
1504 {
1505 struct pipeline_params p;
1506 char *name;
1507 struct pipeline *pipeline;
1508
1509 if (n_tokens != 8) {
1510 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1511 return;
1512 }
1513
1514 name = tokens[1];
1515
1516 if (strcmp(tokens[2], "period") != 0) {
1517 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
1518 return;
1519 }
1520
1521 if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) {
1522 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
1523 return;
1524 }
1525
1526 if (strcmp(tokens[4], "offset_port_id") != 0) {
1527 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
1528 return;
1529 }
1530
1531 if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) {
1532 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
1533 return;
1534 }
1535
1536 if (strcmp(tokens[6], "cpu") != 0) {
1537 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
1538 return;
1539 }
1540
1541 if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) {
1542 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
1543 return;
1544 }
1545
1546 pipeline = pipeline_create(name, &p);
1547 if (pipeline == NULL) {
1548 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1549 return;
1550 }
1551 }
1552
1553 static const char cmd_pipeline_port_in_help[] =
1554 "pipeline <pipeline_name> port in\n"
1555 " bsz <burst_size>\n"
1556 " link <link_name> rxq <queue_id>\n"
1557 " | swq <swq_name>\n"
1558 " | tmgr <tmgr_name>\n"
1559 " | tap <tap_name> mempool <mempool_name> mtu <mtu>\n"
1560 " | kni <kni_name>\n"
1561 " | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n"
1562 " | cryptodev <cryptodev_name> rxq <queue_id>\n"
1563 " [action <port_in_action_profile_name>]\n"
1564 " [disabled]\n";
1565
1566 static void
1567 cmd_pipeline_port_in(char **tokens,
1568 uint32_t n_tokens,
1569 char *out,
1570 size_t out_size)
1571 {
1572 struct port_in_params p;
1573 char *pipeline_name;
1574 uint32_t t0;
1575 int enabled, status;
1576
1577 if (n_tokens < 7) {
1578 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1579 return;
1580 }
1581
1582 pipeline_name = tokens[1];
1583
1584 if (strcmp(tokens[2], "port") != 0) {
1585 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1586 return;
1587 }
1588
1589 if (strcmp(tokens[3], "in") != 0) {
1590 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1591 return;
1592 }
1593
1594 if (strcmp(tokens[4], "bsz") != 0) {
1595 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1596 return;
1597 }
1598
1599 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1600 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1601 return;
1602 }
1603
1604 t0 = 6;
1605
1606 if (strcmp(tokens[t0], "link") == 0) {
1607 if (n_tokens < t0 + 4) {
1608 snprintf(out, out_size, MSG_ARG_MISMATCH,
1609 "pipeline port in link");
1610 return;
1611 }
1612
1613 p.type = PORT_IN_RXQ;
1614
1615 p.dev_name = tokens[t0 + 1];
1616
1617 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
1618 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
1619 return;
1620 }
1621
1622 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) {
1623 snprintf(out, out_size, MSG_ARG_INVALID,
1624 "queue_id");
1625 return;
1626 }
1627 t0 += 4;
1628 } else if (strcmp(tokens[t0], "swq") == 0) {
1629 if (n_tokens < t0 + 2) {
1630 snprintf(out, out_size, MSG_ARG_MISMATCH,
1631 "pipeline port in swq");
1632 return;
1633 }
1634
1635 p.type = PORT_IN_SWQ;
1636
1637 p.dev_name = tokens[t0 + 1];
1638
1639 t0 += 2;
1640 } else if (strcmp(tokens[t0], "tmgr") == 0) {
1641 if (n_tokens < t0 + 2) {
1642 snprintf(out, out_size, MSG_ARG_MISMATCH,
1643 "pipeline port in tmgr");
1644 return;
1645 }
1646
1647 p.type = PORT_IN_TMGR;
1648
1649 p.dev_name = tokens[t0 + 1];
1650
1651 t0 += 2;
1652 } else if (strcmp(tokens[t0], "tap") == 0) {
1653 if (n_tokens < t0 + 6) {
1654 snprintf(out, out_size, MSG_ARG_MISMATCH,
1655 "pipeline port in tap");
1656 return;
1657 }
1658
1659 p.type = PORT_IN_TAP;
1660
1661 p.dev_name = tokens[t0 + 1];
1662
1663 if (strcmp(tokens[t0 + 2], "mempool") != 0) {
1664 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1665 "mempool");
1666 return;
1667 }
1668
1669 p.tap.mempool_name = tokens[t0 + 3];
1670
1671 if (strcmp(tokens[t0 + 4], "mtu") != 0) {
1672 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1673 "mtu");
1674 return;
1675 }
1676
1677 if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) {
1678 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
1679 return;
1680 }
1681
1682 t0 += 6;
1683 } else if (strcmp(tokens[t0], "kni") == 0) {
1684 if (n_tokens < t0 + 2) {
1685 snprintf(out, out_size, MSG_ARG_MISMATCH,
1686 "pipeline port in kni");
1687 return;
1688 }
1689
1690 p.type = PORT_IN_KNI;
1691
1692 p.dev_name = tokens[t0 + 1];
1693
1694 t0 += 2;
1695 } else if (strcmp(tokens[t0], "source") == 0) {
1696 if (n_tokens < t0 + 6) {
1697 snprintf(out, out_size, MSG_ARG_MISMATCH,
1698 "pipeline port in source");
1699 return;
1700 }
1701
1702 p.type = PORT_IN_SOURCE;
1703
1704 p.dev_name = NULL;
1705
1706 if (strcmp(tokens[t0 + 1], "mempool") != 0) {
1707 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1708 "mempool");
1709 return;
1710 }
1711
1712 p.source.mempool_name = tokens[t0 + 2];
1713
1714 if (strcmp(tokens[t0 + 3], "file") != 0) {
1715 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1716 "file");
1717 return;
1718 }
1719
1720 p.source.file_name = tokens[t0 + 4];
1721
1722 if (strcmp(tokens[t0 + 5], "bpp") != 0) {
1723 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1724 "bpp");
1725 return;
1726 }
1727
1728 if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) {
1729 snprintf(out, out_size, MSG_ARG_INVALID,
1730 "n_bytes_per_pkt");
1731 return;
1732 }
1733
1734 t0 += 7;
1735 } else if (strcmp(tokens[t0], "cryptodev") == 0) {
1736 if (n_tokens < t0 + 3) {
1737 snprintf(out, out_size, MSG_ARG_MISMATCH,
1738 "pipeline port in cryptodev");
1739 return;
1740 }
1741
1742 p.type = PORT_IN_CRYPTODEV;
1743
1744 p.dev_name = tokens[t0 + 1];
1745 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) {
1746 snprintf(out, out_size, MSG_ARG_INVALID,
1747 "rxq");
1748 return;
1749 }
1750
1751 p.cryptodev.arg_callback = NULL;
1752 p.cryptodev.f_callback = NULL;
1753
1754 t0 += 4;
1755 } else {
1756 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1757 return;
1758 }
1759
1760 p.action_profile_name = NULL;
1761 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
1762 if (n_tokens < t0 + 2) {
1763 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1764 return;
1765 }
1766
1767 p.action_profile_name = tokens[t0 + 1];
1768
1769 t0 += 2;
1770 }
1771
1772 enabled = 1;
1773 if ((n_tokens > t0) &&
1774 (strcmp(tokens[t0], "disabled") == 0)) {
1775 enabled = 0;
1776
1777 t0 += 1;
1778 }
1779
1780 if (n_tokens != t0) {
1781 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1782 return;
1783 }
1784
1785 status = pipeline_port_in_create(pipeline_name,
1786 &p, enabled);
1787 if (status) {
1788 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1789 return;
1790 }
1791 }
1792
1793 static const char cmd_pipeline_port_out_help[] =
1794 "pipeline <pipeline_name> port out\n"
1795 " bsz <burst_size>\n"
1796 " link <link_name> txq <txq_id>\n"
1797 " | swq <swq_name>\n"
1798 " | tmgr <tmgr_name>\n"
1799 " | tap <tap_name>\n"
1800 " | kni <kni_name>\n"
1801 " | sink [file <file_name> pkts <max_n_pkts>]\n"
1802 " | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset>\n";
1803
1804 static void
1805 cmd_pipeline_port_out(char **tokens,
1806 uint32_t n_tokens,
1807 char *out,
1808 size_t out_size)
1809 {
1810 struct port_out_params p;
1811 char *pipeline_name;
1812 int status;
1813
1814 memset(&p, 0, sizeof(p));
1815
1816 if (n_tokens < 7) {
1817 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1818 return;
1819 }
1820
1821 pipeline_name = tokens[1];
1822
1823 if (strcmp(tokens[2], "port") != 0) {
1824 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1825 return;
1826 }
1827
1828 if (strcmp(tokens[3], "out") != 0) {
1829 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
1830 return;
1831 }
1832
1833 if (strcmp(tokens[4], "bsz") != 0) {
1834 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1835 return;
1836 }
1837
1838 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1839 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1840 return;
1841 }
1842
1843 if (strcmp(tokens[6], "link") == 0) {
1844 if (n_tokens != 10) {
1845 snprintf(out, out_size, MSG_ARG_MISMATCH,
1846 "pipeline port out link");
1847 return;
1848 }
1849
1850 p.type = PORT_OUT_TXQ;
1851
1852 p.dev_name = tokens[7];
1853
1854 if (strcmp(tokens[8], "txq") != 0) {
1855 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
1856 return;
1857 }
1858
1859 if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) {
1860 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1861 return;
1862 }
1863 } else if (strcmp(tokens[6], "swq") == 0) {
1864 if (n_tokens != 8) {
1865 snprintf(out, out_size, MSG_ARG_MISMATCH,
1866 "pipeline port out swq");
1867 return;
1868 }
1869
1870 p.type = PORT_OUT_SWQ;
1871
1872 p.dev_name = tokens[7];
1873 } else if (strcmp(tokens[6], "tmgr") == 0) {
1874 if (n_tokens != 8) {
1875 snprintf(out, out_size, MSG_ARG_MISMATCH,
1876 "pipeline port out tmgr");
1877 return;
1878 }
1879
1880 p.type = PORT_OUT_TMGR;
1881
1882 p.dev_name = tokens[7];
1883 } else if (strcmp(tokens[6], "tap") == 0) {
1884 if (n_tokens != 8) {
1885 snprintf(out, out_size, MSG_ARG_MISMATCH,
1886 "pipeline port out tap");
1887 return;
1888 }
1889
1890 p.type = PORT_OUT_TAP;
1891
1892 p.dev_name = tokens[7];
1893 } else if (strcmp(tokens[6], "kni") == 0) {
1894 if (n_tokens != 8) {
1895 snprintf(out, out_size, MSG_ARG_MISMATCH,
1896 "pipeline port out kni");
1897 return;
1898 }
1899
1900 p.type = PORT_OUT_KNI;
1901
1902 p.dev_name = tokens[7];
1903 } else if (strcmp(tokens[6], "sink") == 0) {
1904 if ((n_tokens != 7) && (n_tokens != 11)) {
1905 snprintf(out, out_size, MSG_ARG_MISMATCH,
1906 "pipeline port out sink");
1907 return;
1908 }
1909
1910 p.type = PORT_OUT_SINK;
1911
1912 p.dev_name = NULL;
1913
1914 if (n_tokens == 7) {
1915 p.sink.file_name = NULL;
1916 p.sink.max_n_pkts = 0;
1917 } else {
1918 if (strcmp(tokens[7], "file") != 0) {
1919 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1920 "file");
1921 return;
1922 }
1923
1924 p.sink.file_name = tokens[8];
1925
1926 if (strcmp(tokens[9], "pkts") != 0) {
1927 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
1928 return;
1929 }
1930
1931 if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) {
1932 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
1933 return;
1934 }
1935 }
1936
1937 } else if (strcmp(tokens[6], "cryptodev") == 0) {
1938 if (n_tokens != 12) {
1939 snprintf(out, out_size, MSG_ARG_MISMATCH,
1940 "pipeline port out cryptodev");
1941 return;
1942 }
1943
1944 p.type = PORT_OUT_CRYPTODEV;
1945
1946 p.dev_name = tokens[7];
1947
1948 if (strcmp(tokens[8], "txq")) {
1949 snprintf(out, out_size, MSG_ARG_MISMATCH,
1950 "pipeline port out cryptodev");
1951 return;
1952 }
1953
1954 if (parser_read_uint16(&p.cryptodev.queue_id, tokens[9])
1955 != 0) {
1956 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1957 return;
1958 }
1959
1960 if (strcmp(tokens[10], "offset")) {
1961 snprintf(out, out_size, MSG_ARG_MISMATCH,
1962 "pipeline port out cryptodev");
1963 return;
1964 }
1965
1966 if (parser_read_uint32(&p.cryptodev.op_offset, tokens[11])
1967 != 0) {
1968 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1969 return;
1970 }
1971 } else {
1972 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1973 return;
1974 }
1975
1976 status = pipeline_port_out_create(pipeline_name, &p);
1977 if (status) {
1978 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1979 return;
1980 }
1981 }
1982
1983 static const char cmd_pipeline_table_help[] =
1984 "pipeline <pipeline_name> table\n"
1985 " match\n"
1986 " acl\n"
1987 " ipv4 | ipv6\n"
1988 " offset <ip_header_offset>\n"
1989 " size <n_rules>\n"
1990 " | array\n"
1991 " offset <key_offset>\n"
1992 " size <n_keys>\n"
1993 " | hash\n"
1994 " ext | lru\n"
1995 " key <key_size>\n"
1996 " mask <key_mask>\n"
1997 " offset <key_offset>\n"
1998 " buckets <n_buckets>\n"
1999 " size <n_keys>\n"
2000 " | lpm\n"
2001 " ipv4 | ipv6\n"
2002 " offset <ip_header_offset>\n"
2003 " size <n_rules>\n"
2004 " | stub\n"
2005 " [action <table_action_profile_name>]\n";
2006
2007 static void
2008 cmd_pipeline_table(char **tokens,
2009 uint32_t n_tokens,
2010 char *out,
2011 size_t out_size)
2012 {
2013 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
2014 struct table_params p;
2015 char *pipeline_name;
2016 uint32_t t0;
2017 int status;
2018
2019 if (n_tokens < 5) {
2020 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2021 return;
2022 }
2023
2024 pipeline_name = tokens[1];
2025
2026 if (strcmp(tokens[2], "table") != 0) {
2027 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
2028 return;
2029 }
2030
2031 if (strcmp(tokens[3], "match") != 0) {
2032 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
2033 return;
2034 }
2035
2036 t0 = 4;
2037 if (strcmp(tokens[t0], "acl") == 0) {
2038 if (n_tokens < t0 + 6) {
2039 snprintf(out, out_size, MSG_ARG_MISMATCH,
2040 "pipeline table acl");
2041 return;
2042 }
2043
2044 p.match_type = TABLE_ACL;
2045
2046 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
2047 p.match.acl.ip_version = 1;
2048 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
2049 p.match.acl.ip_version = 0;
2050 else {
2051 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2052 "ipv4 or ipv6");
2053 return;
2054 }
2055
2056 if (strcmp(tokens[t0 + 2], "offset") != 0) {
2057 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
2058 return;
2059 }
2060
2061 if (parser_read_uint32(&p.match.acl.ip_header_offset,
2062 tokens[t0 + 3]) != 0) {
2063 snprintf(out, out_size, MSG_ARG_INVALID,
2064 "ip_header_offset");
2065 return;
2066 }
2067
2068 if (strcmp(tokens[t0 + 4], "size") != 0) {
2069 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
2070 return;
2071 }
2072
2073 if (parser_read_uint32(&p.match.acl.n_rules,
2074 tokens[t0 + 5]) != 0) {
2075 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
2076 return;
2077 }
2078
2079 t0 += 6;
2080 } else if (strcmp(tokens[t0], "array") == 0) {
2081 if (n_tokens < t0 + 5) {
2082 snprintf(out, out_size, MSG_ARG_MISMATCH,
2083 "pipeline table array");
2084 return;
2085 }
2086
2087 p.match_type = TABLE_ARRAY;
2088
2089 if (strcmp(tokens[t0 + 1], "offset") != 0) {
2090 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
2091 return;
2092 }
2093
2094 if (parser_read_uint32(&p.match.array.key_offset,
2095 tokens[t0 + 2]) != 0) {
2096 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
2097 return;
2098 }
2099
2100 if (strcmp(tokens[t0 + 3], "size") != 0) {
2101 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
2102 return;
2103 }
2104
2105 if (parser_read_uint32(&p.match.array.n_keys,
2106 tokens[t0 + 4]) != 0) {
2107 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
2108 return;
2109 }
2110
2111 t0 += 5;
2112 } else if (strcmp(tokens[t0], "hash") == 0) {
2113 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
2114
2115 if (n_tokens < t0 + 12) {
2116 snprintf(out, out_size, MSG_ARG_MISMATCH,
2117 "pipeline table hash");
2118 return;
2119 }
2120
2121 p.match_type = TABLE_HASH;
2122
2123 if (strcmp(tokens[t0 + 1], "ext") == 0)
2124 p.match.hash.extendable_bucket = 1;
2125 else if (strcmp(tokens[t0 + 1], "lru") == 0)
2126 p.match.hash.extendable_bucket = 0;
2127 else {
2128 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2129 "ext or lru");
2130 return;
2131 }
2132
2133 if (strcmp(tokens[t0 + 2], "key") != 0) {
2134 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
2135 return;
2136 }
2137
2138 if ((parser_read_uint32(&p.match.hash.key_size,
2139 tokens[t0 + 3]) != 0) ||
2140 (p.match.hash.key_size == 0) ||
2141 (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) {
2142 snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
2143 return;
2144 }
2145
2146 if (strcmp(tokens[t0 + 4], "mask") != 0) {
2147 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
2148 return;
2149 }
2150
2151 if ((parse_hex_string(tokens[t0 + 5],
2152 key_mask, &key_mask_size) != 0) ||
2153 (key_mask_size != p.match.hash.key_size)) {
2154 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
2155 return;
2156 }
2157 p.match.hash.key_mask = key_mask;
2158
2159 if (strcmp(tokens[t0 + 6], "offset") != 0) {
2160 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
2161 return;
2162 }
2163
2164 if (parser_read_uint32(&p.match.hash.key_offset,
2165 tokens[t0 + 7]) != 0) {
2166 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
2167 return;
2168 }
2169
2170 if (strcmp(tokens[t0 + 8], "buckets") != 0) {
2171 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
2172 return;
2173 }
2174
2175 if (parser_read_uint32(&p.match.hash.n_buckets,
2176 tokens[t0 + 9]) != 0) {
2177 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
2178 return;
2179 }
2180
2181 if (strcmp(tokens[t0 + 10], "size") != 0) {
2182 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
2183 return;
2184 }
2185
2186 if (parser_read_uint32(&p.match.hash.n_keys,
2187 tokens[t0 + 11]) != 0) {
2188 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
2189 return;
2190 }
2191
2192 t0 += 12;
2193 } else if (strcmp(tokens[t0], "lpm") == 0) {
2194 if (n_tokens < t0 + 6) {
2195 snprintf(out, out_size, MSG_ARG_MISMATCH,
2196 "pipeline table lpm");
2197 return;
2198 }
2199
2200 p.match_type = TABLE_LPM;
2201
2202 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
2203 p.match.lpm.key_size = 4;
2204 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
2205 p.match.lpm.key_size = 16;
2206 else {
2207 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2208 "ipv4 or ipv6");
2209 return;
2210 }
2211
2212 if (strcmp(tokens[t0 + 2], "offset") != 0) {
2213 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
2214 return;
2215 }
2216
2217 if (parser_read_uint32(&p.match.lpm.key_offset,
2218 tokens[t0 + 3]) != 0) {
2219 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
2220 return;
2221 }
2222
2223 if (strcmp(tokens[t0 + 4], "size") != 0) {
2224 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
2225 return;
2226 }
2227
2228 if (parser_read_uint32(&p.match.lpm.n_rules,
2229 tokens[t0 + 5]) != 0) {
2230 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
2231 return;
2232 }
2233
2234 t0 += 6;
2235 } else if (strcmp(tokens[t0], "stub") == 0) {
2236 p.match_type = TABLE_STUB;
2237
2238 t0 += 1;
2239 } else {
2240 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
2241 return;
2242 }
2243
2244 p.action_profile_name = NULL;
2245 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
2246 if (n_tokens < t0 + 2) {
2247 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
2248 return;
2249 }
2250
2251 p.action_profile_name = tokens[t0 + 1];
2252
2253 t0 += 2;
2254 }
2255
2256 if (n_tokens > t0) {
2257 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2258 return;
2259 }
2260
2261 status = pipeline_table_create(pipeline_name, &p);
2262 if (status) {
2263 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2264 return;
2265 }
2266 }
2267
2268 static const char cmd_pipeline_port_in_table_help[] =
2269 "pipeline <pipeline_name> port in <port_id> table <table_id>\n";
2270
2271 static void
2272 cmd_pipeline_port_in_table(char **tokens,
2273 uint32_t n_tokens,
2274 char *out,
2275 size_t out_size)
2276 {
2277 char *pipeline_name;
2278 uint32_t port_id, table_id;
2279 int status;
2280
2281 if (n_tokens != 7) {
2282 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2283 return;
2284 }
2285
2286 pipeline_name = tokens[1];
2287
2288 if (strcmp(tokens[2], "port") != 0) {
2289 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2290 return;
2291 }
2292
2293 if (strcmp(tokens[3], "in") != 0) {
2294 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2295 return;
2296 }
2297
2298 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2299 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2300 return;
2301 }
2302
2303 if (strcmp(tokens[5], "table") != 0) {
2304 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
2305 return;
2306 }
2307
2308 if (parser_read_uint32(&table_id, tokens[6]) != 0) {
2309 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
2310 return;
2311 }
2312
2313 status = pipeline_port_in_connect_to_table(pipeline_name,
2314 port_id,
2315 table_id);
2316 if (status) {
2317 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2318 return;
2319 }
2320 }
2321
2322
2323 static const char cmd_pipeline_port_in_stats_help[] =
2324 "pipeline <pipeline_name> port in <port_id> stats read [clear]\n";
2325
2326 #define MSG_PIPELINE_PORT_IN_STATS \
2327 "Pkts in: %" PRIu64 "\n" \
2328 "Pkts dropped by AH: %" PRIu64 "\n" \
2329 "Pkts dropped by other: %" PRIu64 "\n"
2330
2331 static void
2332 cmd_pipeline_port_in_stats(char **tokens,
2333 uint32_t n_tokens,
2334 char *out,
2335 size_t out_size)
2336 {
2337 struct rte_pipeline_port_in_stats stats;
2338 char *pipeline_name;
2339 uint32_t port_id;
2340 int clear, status;
2341
2342 if ((n_tokens != 7) && (n_tokens != 8)) {
2343 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2344 return;
2345 }
2346
2347 pipeline_name = tokens[1];
2348
2349 if (strcmp(tokens[2], "port") != 0) {
2350 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2351 return;
2352 }
2353
2354 if (strcmp(tokens[3], "in") != 0) {
2355 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2356 return;
2357 }
2358
2359 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2360 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2361 return;
2362 }
2363
2364 if (strcmp(tokens[5], "stats") != 0) {
2365 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2366 return;
2367 }
2368
2369 if (strcmp(tokens[6], "read") != 0) {
2370 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2371 return;
2372 }
2373
2374 clear = 0;
2375 if (n_tokens == 8) {
2376 if (strcmp(tokens[7], "clear") != 0) {
2377 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2378 return;
2379 }
2380
2381 clear = 1;
2382 }
2383
2384 status = pipeline_port_in_stats_read(pipeline_name,
2385 port_id,
2386 &stats,
2387 clear);
2388 if (status) {
2389 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2390 return;
2391 }
2392
2393 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
2394 stats.stats.n_pkts_in,
2395 stats.n_pkts_dropped_by_ah,
2396 stats.stats.n_pkts_drop);
2397 }
2398
2399
2400 static const char cmd_pipeline_port_in_enable_help[] =
2401 "pipeline <pipeline_name> port in <port_id> enable\n";
2402
2403 static void
2404 cmd_pipeline_port_in_enable(char **tokens,
2405 uint32_t n_tokens,
2406 char *out,
2407 size_t out_size)
2408 {
2409 char *pipeline_name;
2410 uint32_t port_id;
2411 int status;
2412
2413 if (n_tokens != 6) {
2414 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2415 return;
2416 }
2417
2418 pipeline_name = tokens[1];
2419
2420 if (strcmp(tokens[2], "port") != 0) {
2421 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2422 return;
2423 }
2424
2425 if (strcmp(tokens[3], "in") != 0) {
2426 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2427 return;
2428 }
2429
2430 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2431 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2432 return;
2433 }
2434
2435 if (strcmp(tokens[5], "enable") != 0) {
2436 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
2437 return;
2438 }
2439
2440 status = pipeline_port_in_enable(pipeline_name, port_id);
2441 if (status) {
2442 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2443 return;
2444 }
2445 }
2446
2447
2448 static const char cmd_pipeline_port_in_disable_help[] =
2449 "pipeline <pipeline_name> port in <port_id> disable\n";
2450
2451 static void
2452 cmd_pipeline_port_in_disable(char **tokens,
2453 uint32_t n_tokens,
2454 char *out,
2455 size_t out_size)
2456 {
2457 char *pipeline_name;
2458 uint32_t port_id;
2459 int status;
2460
2461 if (n_tokens != 6) {
2462 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2463 return;
2464 }
2465
2466 pipeline_name = tokens[1];
2467
2468 if (strcmp(tokens[2], "port") != 0) {
2469 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2470 return;
2471 }
2472
2473 if (strcmp(tokens[3], "in") != 0) {
2474 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2475 return;
2476 }
2477
2478 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2479 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2480 return;
2481 }
2482
2483 if (strcmp(tokens[5], "disable") != 0) {
2484 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2485 return;
2486 }
2487
2488 status = pipeline_port_in_disable(pipeline_name, port_id);
2489 if (status) {
2490 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2491 return;
2492 }
2493 }
2494
2495
2496 static const char cmd_pipeline_port_out_stats_help[] =
2497 "pipeline <pipeline_name> port out <port_id> stats read [clear]\n";
2498
2499 #define MSG_PIPELINE_PORT_OUT_STATS \
2500 "Pkts in: %" PRIu64 "\n" \
2501 "Pkts dropped by AH: %" PRIu64 "\n" \
2502 "Pkts dropped by other: %" PRIu64 "\n"
2503
2504 static void
2505 cmd_pipeline_port_out_stats(char **tokens,
2506 uint32_t n_tokens,
2507 char *out,
2508 size_t out_size)
2509 {
2510 struct rte_pipeline_port_out_stats stats;
2511 char *pipeline_name;
2512 uint32_t port_id;
2513 int clear, status;
2514
2515 if ((n_tokens != 7) && (n_tokens != 8)) {
2516 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2517 return;
2518 }
2519
2520 pipeline_name = tokens[1];
2521
2522 if (strcmp(tokens[2], "port") != 0) {
2523 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2524 return;
2525 }
2526
2527 if (strcmp(tokens[3], "out") != 0) {
2528 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
2529 return;
2530 }
2531
2532 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2533 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2534 return;
2535 }
2536
2537 if (strcmp(tokens[5], "stats") != 0) {
2538 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2539 return;
2540 }
2541
2542 if (strcmp(tokens[6], "read") != 0) {
2543 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2544 return;
2545 }
2546
2547 clear = 0;
2548 if (n_tokens == 8) {
2549 if (strcmp(tokens[7], "clear") != 0) {
2550 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2551 return;
2552 }
2553
2554 clear = 1;
2555 }
2556
2557 status = pipeline_port_out_stats_read(pipeline_name,
2558 port_id,
2559 &stats,
2560 clear);
2561 if (status) {
2562 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2563 return;
2564 }
2565
2566 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
2567 stats.stats.n_pkts_in,
2568 stats.n_pkts_dropped_by_ah,
2569 stats.stats.n_pkts_drop);
2570 }
2571
2572
2573 static const char cmd_pipeline_table_stats_help[] =
2574 "pipeline <pipeline_name> table <table_id> stats read [clear]\n";
2575
2576 #define MSG_PIPELINE_TABLE_STATS \
2577 "Pkts in: %" PRIu64 "\n" \
2578 "Pkts in with lookup miss: %" PRIu64 "\n" \
2579 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \
2580 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \
2581 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \
2582 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
2583
2584 static void
2585 cmd_pipeline_table_stats(char **tokens,
2586 uint32_t n_tokens,
2587 char *out,
2588 size_t out_size)
2589 {
2590 struct rte_pipeline_table_stats stats;
2591 char *pipeline_name;
2592 uint32_t table_id;
2593 int clear, status;
2594
2595 if ((n_tokens != 6) && (n_tokens != 7)) {
2596 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2597 return;
2598 }
2599
2600 pipeline_name = tokens[1];
2601
2602 if (strcmp(tokens[2], "table") != 0) {
2603 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2604 return;
2605 }
2606
2607 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
2608 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
2609 return;
2610 }
2611
2612 if (strcmp(tokens[4], "stats") != 0) {
2613 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2614 return;
2615 }
2616
2617 if (strcmp(tokens[5], "read") != 0) {
2618 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2619 return;
2620 }
2621
2622 clear = 0;
2623 if (n_tokens == 7) {
2624 if (strcmp(tokens[6], "clear") != 0) {
2625 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2626 return;
2627 }
2628
2629 clear = 1;
2630 }
2631
2632 status = pipeline_table_stats_read(pipeline_name,
2633 table_id,
2634 &stats,
2635 clear);
2636 if (status) {
2637 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2638 return;
2639 }
2640
2641 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
2642 stats.stats.n_pkts_in,
2643 stats.stats.n_pkts_lookup_miss,
2644 stats.n_pkts_dropped_by_lkp_hit_ah,
2645 stats.n_pkts_dropped_lkp_hit,
2646 stats.n_pkts_dropped_by_lkp_miss_ah,
2647 stats.n_pkts_dropped_lkp_miss);
2648 }
2649
2650 /**
2651 * <match> ::=
2652 *
2653 * match
2654 * acl
2655 * priority <priority>
2656 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
2657 * <sp0> <sp1> <dp0> <dp1> <proto>
2658 * | array <pos>
2659 * | hash
2660 * raw <key>
2661 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
2662 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
2663 * | ipv4_addr <addr>
2664 * | ipv6_addr <addr>
2665 * | qinq <svlan> <cvlan>
2666 * | lpm
2667 * ipv4 | ipv6 <addr> <depth>
2668 */
2669 struct pkt_key_qinq {
2670 uint16_t ethertype_svlan;
2671 uint16_t svlan;
2672 uint16_t ethertype_cvlan;
2673 uint16_t cvlan;
2674 } __rte_packed;
2675
2676 struct pkt_key_ipv4_5tuple {
2677 uint8_t time_to_live;
2678 uint8_t proto;
2679 uint16_t hdr_checksum;
2680 uint32_t sa;
2681 uint32_t da;
2682 uint16_t sp;
2683 uint16_t dp;
2684 } __rte_packed;
2685
2686 struct pkt_key_ipv6_5tuple {
2687 uint16_t payload_length;
2688 uint8_t proto;
2689 uint8_t hop_limit;
2690 uint8_t sa[16];
2691 uint8_t da[16];
2692 uint16_t sp;
2693 uint16_t dp;
2694 } __rte_packed;
2695
2696 struct pkt_key_ipv4_addr {
2697 uint32_t addr;
2698 } __rte_packed;
2699
2700 struct pkt_key_ipv6_addr {
2701 uint8_t addr[16];
2702 } __rte_packed;
2703
2704 static uint32_t
2705 parse_match(char **tokens,
2706 uint32_t n_tokens,
2707 char *out,
2708 size_t out_size,
2709 struct table_rule_match *m)
2710 {
2711 memset(m, 0, sizeof(*m));
2712
2713 if (n_tokens < 2)
2714 return 0;
2715
2716 if (strcmp(tokens[0], "match") != 0) {
2717 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
2718 return 0;
2719 }
2720
2721 if (strcmp(tokens[1], "acl") == 0) {
2722 if (n_tokens < 14) {
2723 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2724 return 0;
2725 }
2726
2727 m->match_type = TABLE_ACL;
2728
2729 if (strcmp(tokens[2], "priority") != 0) {
2730 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
2731 return 0;
2732 }
2733
2734 if (parser_read_uint32(&m->match.acl.priority,
2735 tokens[3]) != 0) {
2736 snprintf(out, out_size, MSG_ARG_INVALID, "priority");
2737 return 0;
2738 }
2739
2740 if (strcmp(tokens[4], "ipv4") == 0) {
2741 struct in_addr saddr, daddr;
2742
2743 m->match.acl.ip_version = 1;
2744
2745 if (parse_ipv4_addr(tokens[5], &saddr) != 0) {
2746 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2747 return 0;
2748 }
2749 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
2750
2751 if (parse_ipv4_addr(tokens[7], &daddr) != 0) {
2752 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2753 return 0;
2754 }
2755 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
2756 } else if (strcmp(tokens[4], "ipv6") == 0) {
2757 struct in6_addr saddr, daddr;
2758
2759 m->match.acl.ip_version = 0;
2760
2761 if (parse_ipv6_addr(tokens[5], &saddr) != 0) {
2762 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2763 return 0;
2764 }
2765 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
2766
2767 if (parse_ipv6_addr(tokens[7], &daddr) != 0) {
2768 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2769 return 0;
2770 }
2771 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
2772 } else {
2773 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2774 "ipv4 or ipv6");
2775 return 0;
2776 }
2777
2778 if (parser_read_uint32(&m->match.acl.sa_depth,
2779 tokens[6]) != 0) {
2780 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
2781 return 0;
2782 }
2783
2784 if (parser_read_uint32(&m->match.acl.da_depth,
2785 tokens[8]) != 0) {
2786 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
2787 return 0;
2788 }
2789
2790 if (parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
2791 snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
2792 return 0;
2793 }
2794
2795 if (parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
2796 snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
2797 return 0;
2798 }
2799
2800 if (parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
2801 snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
2802 return 0;
2803 }
2804
2805 if (parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
2806 snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
2807 return 0;
2808 }
2809
2810 if (parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
2811 snprintf(out, out_size, MSG_ARG_INVALID, "proto");
2812 return 0;
2813 }
2814
2815 m->match.acl.proto_mask = 0xff;
2816
2817 return 14;
2818 } /* acl */
2819
2820 if (strcmp(tokens[1], "array") == 0) {
2821 if (n_tokens < 3) {
2822 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2823 return 0;
2824 }
2825
2826 m->match_type = TABLE_ARRAY;
2827
2828 if (parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
2829 snprintf(out, out_size, MSG_ARG_INVALID, "pos");
2830 return 0;
2831 }
2832
2833 return 3;
2834 } /* array */
2835
2836 if (strcmp(tokens[1], "hash") == 0) {
2837 if (n_tokens < 3) {
2838 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2839 return 0;
2840 }
2841
2842 m->match_type = TABLE_HASH;
2843
2844 if (strcmp(tokens[2], "raw") == 0) {
2845 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
2846
2847 if (n_tokens < 4) {
2848 snprintf(out, out_size, MSG_ARG_MISMATCH,
2849 tokens[0]);
2850 return 0;
2851 }
2852
2853 if (parse_hex_string(tokens[3],
2854 m->match.hash.key, &key_size) != 0) {
2855 snprintf(out, out_size, MSG_ARG_INVALID, "key");
2856 return 0;
2857 }
2858
2859 return 4;
2860 } /* hash raw */
2861
2862 if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
2863 struct pkt_key_ipv4_5tuple *ipv4 =
2864 (struct pkt_key_ipv4_5tuple *) m->match.hash.key;
2865 struct in_addr saddr, daddr;
2866 uint16_t sp, dp;
2867 uint8_t proto;
2868
2869 if (n_tokens < 8) {
2870 snprintf(out, out_size, MSG_ARG_MISMATCH,
2871 tokens[0]);
2872 return 0;
2873 }
2874
2875 if (parse_ipv4_addr(tokens[3], &saddr) != 0) {
2876 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2877 return 0;
2878 }
2879
2880 if (parse_ipv4_addr(tokens[4], &daddr) != 0) {
2881 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2882 return 0;
2883 }
2884
2885 if (parser_read_uint16(&sp, tokens[5]) != 0) {
2886 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2887 return 0;
2888 }
2889
2890 if (parser_read_uint16(&dp, tokens[6]) != 0) {
2891 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2892 return 0;
2893 }
2894
2895 if (parser_read_uint8(&proto, tokens[7]) != 0) {
2896 snprintf(out, out_size, MSG_ARG_INVALID,
2897 "proto");
2898 return 0;
2899 }
2900
2901 ipv4->sa = saddr.s_addr;
2902 ipv4->da = daddr.s_addr;
2903 ipv4->sp = rte_cpu_to_be_16(sp);
2904 ipv4->dp = rte_cpu_to_be_16(dp);
2905 ipv4->proto = proto;
2906
2907 return 8;
2908 } /* hash ipv4_5tuple */
2909
2910 if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
2911 struct pkt_key_ipv6_5tuple *ipv6 =
2912 (struct pkt_key_ipv6_5tuple *) m->match.hash.key;
2913 struct in6_addr saddr, daddr;
2914 uint16_t sp, dp;
2915 uint8_t proto;
2916
2917 if (n_tokens < 8) {
2918 snprintf(out, out_size, MSG_ARG_MISMATCH,
2919 tokens[0]);
2920 return 0;
2921 }
2922
2923 if (parse_ipv6_addr(tokens[3], &saddr) != 0) {
2924 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2925 return 0;
2926 }
2927
2928 if (parse_ipv6_addr(tokens[4], &daddr) != 0) {
2929 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2930 return 0;
2931 }
2932
2933 if (parser_read_uint16(&sp, tokens[5]) != 0) {
2934 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2935 return 0;
2936 }
2937
2938 if (parser_read_uint16(&dp, tokens[6]) != 0) {
2939 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2940 return 0;
2941 }
2942
2943 if (parser_read_uint8(&proto, tokens[7]) != 0) {
2944 snprintf(out, out_size, MSG_ARG_INVALID,
2945 "proto");
2946 return 0;
2947 }
2948
2949 memcpy(ipv6->sa, saddr.s6_addr, 16);
2950 memcpy(ipv6->da, daddr.s6_addr, 16);
2951 ipv6->sp = rte_cpu_to_be_16(sp);
2952 ipv6->dp = rte_cpu_to_be_16(dp);
2953 ipv6->proto = proto;
2954
2955 return 8;
2956 } /* hash ipv6_5tuple */
2957
2958 if (strcmp(tokens[2], "ipv4_addr") == 0) {
2959 struct pkt_key_ipv4_addr *ipv4_addr =
2960 (struct pkt_key_ipv4_addr *) m->match.hash.key;
2961 struct in_addr addr;
2962
2963 if (n_tokens < 4) {
2964 snprintf(out, out_size, MSG_ARG_MISMATCH,
2965 tokens[0]);
2966 return 0;
2967 }
2968
2969 if (parse_ipv4_addr(tokens[3], &addr) != 0) {
2970 snprintf(out, out_size, MSG_ARG_INVALID,
2971 "addr");
2972 return 0;
2973 }
2974
2975 ipv4_addr->addr = addr.s_addr;
2976
2977 return 4;
2978 } /* hash ipv4_addr */
2979
2980 if (strcmp(tokens[2], "ipv6_addr") == 0) {
2981 struct pkt_key_ipv6_addr *ipv6_addr =
2982 (struct pkt_key_ipv6_addr *) m->match.hash.key;
2983 struct in6_addr addr;
2984
2985 if (n_tokens < 4) {
2986 snprintf(out, out_size, MSG_ARG_MISMATCH,
2987 tokens[0]);
2988 return 0;
2989 }
2990
2991 if (parse_ipv6_addr(tokens[3], &addr) != 0) {
2992 snprintf(out, out_size, MSG_ARG_INVALID,
2993 "addr");
2994 return 0;
2995 }
2996
2997 memcpy(ipv6_addr->addr, addr.s6_addr, 16);
2998
2999 return 4;
3000 } /* hash ipv6_5tuple */
3001
3002 if (strcmp(tokens[2], "qinq") == 0) {
3003 struct pkt_key_qinq *qinq =
3004 (struct pkt_key_qinq *) m->match.hash.key;
3005 uint16_t svlan, cvlan;
3006
3007 if (n_tokens < 5) {
3008 snprintf(out, out_size, MSG_ARG_MISMATCH,
3009 tokens[0]);
3010 return 0;
3011 }
3012
3013 if ((parser_read_uint16(&svlan, tokens[3]) != 0) ||
3014 (svlan > 0xFFF)) {
3015 snprintf(out, out_size, MSG_ARG_INVALID,
3016 "svlan");
3017 return 0;
3018 }
3019
3020 if ((parser_read_uint16(&cvlan, tokens[4]) != 0) ||
3021 (cvlan > 0xFFF)) {
3022 snprintf(out, out_size, MSG_ARG_INVALID,
3023 "cvlan");
3024 return 0;
3025 }
3026
3027 qinq->svlan = rte_cpu_to_be_16(svlan);
3028 qinq->cvlan = rte_cpu_to_be_16(cvlan);
3029
3030 return 5;
3031 } /* hash qinq */
3032
3033 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3034 return 0;
3035 } /* hash */
3036
3037 if (strcmp(tokens[1], "lpm") == 0) {
3038 if (n_tokens < 5) {
3039 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3040 return 0;
3041 }
3042
3043 m->match_type = TABLE_LPM;
3044
3045 if (strcmp(tokens[2], "ipv4") == 0) {
3046 struct in_addr addr;
3047
3048 m->match.lpm.ip_version = 1;
3049
3050 if (parse_ipv4_addr(tokens[3], &addr) != 0) {
3051 snprintf(out, out_size, MSG_ARG_INVALID,
3052 "addr");
3053 return 0;
3054 }
3055
3056 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
3057 } else if (strcmp(tokens[2], "ipv6") == 0) {
3058 struct in6_addr addr;
3059
3060 m->match.lpm.ip_version = 0;
3061
3062 if (parse_ipv6_addr(tokens[3], &addr) != 0) {
3063 snprintf(out, out_size, MSG_ARG_INVALID,
3064 "addr");
3065 return 0;
3066 }
3067
3068 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
3069 } else {
3070 snprintf(out, out_size, MSG_ARG_MISMATCH,
3071 "ipv4 or ipv6");
3072 return 0;
3073 }
3074
3075 if (parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
3076 snprintf(out, out_size, MSG_ARG_INVALID, "depth");
3077 return 0;
3078 }
3079
3080 return 5;
3081 } /* lpm */
3082
3083 snprintf(out, out_size, MSG_ARG_MISMATCH,
3084 "acl or array or hash or lpm");
3085 return 0;
3086 }
3087
3088 /**
3089 * table_action ::=
3090 *
3091 * action
3092 * fwd
3093 * drop
3094 * | port <port_id>
3095 * | meta
3096 * | table <table_id>
3097 * [balance <out0> ... <out7>]
3098 * [meter
3099 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
3100 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
3101 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
3102 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
3103 * [tm subport <subport_id> pipe <pipe_id>]
3104 * [encap
3105 * ether <da> <sa>
3106 * | vlan <da> <sa> <pcp> <dei> <vid>
3107 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
3108 * | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id>
3109 * | mpls unicast | multicast
3110 * <da> <sa>
3111 * label0 <label> <tc> <ttl>
3112 * [label1 <label> <tc> <ttl>
3113 * [label2 <label> <tc> <ttl>
3114 * [label3 <label> <tc> <ttl>]]]
3115 * | pppoe <da> <sa> <session_id>
3116 * | vxlan ether <da> <sa>
3117 * [vlan <pcp> <dei> <vid>]
3118 * ipv4 <sa> <da> <dscp> <ttl>
3119 * | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit>
3120 * udp <sp> <dp>
3121 * vxlan <vni>]
3122 * [nat ipv4 | ipv6 <addr> <port>]
3123 * [ttl dec | keep]
3124 * [stats]
3125 * [time]
3126 * [sym_crypto
3127 * encrypt | decrypt
3128 * type
3129 * | cipher
3130 * cipher_algo <algo> cipher_key <key> cipher_iv <iv>
3131 * | cipher_auth
3132 * cipher_algo <algo> cipher_key <key> cipher_iv <iv>
3133 * auth_algo <algo> auth_key <key> digest_size <size>
3134 * | aead
3135 * aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad>
3136 * digest_size <size>
3137 * data_offset <data_offset>]
3138 * [tag <tag>]
3139 * [decap <n>]
3140 *
3141 * where:
3142 * <pa> ::= g | y | r | drop
3143 */
3144 static uint32_t
3145 parse_table_action_fwd(char **tokens,
3146 uint32_t n_tokens,
3147 struct table_rule_action *a)
3148 {
3149 if ((n_tokens == 0) || (strcmp(tokens[0], "fwd") != 0))
3150 return 0;
3151
3152 tokens++;
3153 n_tokens--;
3154
3155 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
3156 a->fwd.action = RTE_PIPELINE_ACTION_DROP;
3157 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
3158 return 1 + 1;
3159 }
3160
3161 if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
3162 uint32_t id;
3163
3164 if ((n_tokens < 2) ||
3165 parser_read_uint32(&id, tokens[1]))
3166 return 0;
3167
3168 a->fwd.action = RTE_PIPELINE_ACTION_PORT;
3169 a->fwd.id = id;
3170 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
3171 return 1 + 2;
3172 }
3173
3174 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
3175 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
3176 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
3177 return 1 + 1;
3178 }
3179
3180 if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
3181 uint32_t id;
3182
3183 if ((n_tokens < 2) ||
3184 parser_read_uint32(&id, tokens[1]))
3185 return 0;
3186
3187 a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
3188 a->fwd.id = id;
3189 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
3190 return 1 + 2;
3191 }
3192
3193 return 0;
3194 }
3195
3196 static uint32_t
3197 parse_table_action_balance(char **tokens,
3198 uint32_t n_tokens,
3199 struct table_rule_action *a)
3200 {
3201 uint32_t i;
3202
3203 if ((n_tokens == 0) || (strcmp(tokens[0], "balance") != 0))
3204 return 0;
3205
3206 tokens++;
3207 n_tokens--;
3208
3209 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
3210 return 0;
3211
3212 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
3213 if (parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
3214 return 0;
3215
3216 a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
3217 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
3218
3219 }
3220
3221 static int
3222 parse_policer_action(char *token, enum rte_table_action_policer *a)
3223 {
3224 if (strcmp(token, "g") == 0) {
3225 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
3226 return 0;
3227 }
3228
3229 if (strcmp(token, "y") == 0) {
3230 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
3231 return 0;
3232 }
3233
3234 if (strcmp(token, "r") == 0) {
3235 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
3236 return 0;
3237 }
3238
3239 if (strcmp(token, "drop") == 0) {
3240 *a = RTE_TABLE_ACTION_POLICER_DROP;
3241 return 0;
3242 }
3243
3244 return -1;
3245 }
3246
3247 static uint32_t
3248 parse_table_action_meter_tc(char **tokens,
3249 uint32_t n_tokens,
3250 struct rte_table_action_mtr_tc_params *mtr)
3251 {
3252 if ((n_tokens < 9) ||
3253 strcmp(tokens[0], "meter") ||
3254 parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
3255 strcmp(tokens[2], "policer") ||
3256 strcmp(tokens[3], "g") ||
3257 parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) ||
3258 strcmp(tokens[5], "y") ||
3259 parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) ||
3260 strcmp(tokens[7], "r") ||
3261 parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED]))
3262 return 0;
3263
3264 return 9;
3265 }
3266
3267 static uint32_t
3268 parse_table_action_meter(char **tokens,
3269 uint32_t n_tokens,
3270 struct table_rule_action *a)
3271 {
3272 if ((n_tokens == 0) || strcmp(tokens[0], "meter"))
3273 return 0;
3274
3275 tokens++;
3276 n_tokens--;
3277
3278 if ((n_tokens < 10) ||
3279 strcmp(tokens[0], "tc0") ||
3280 (parse_table_action_meter_tc(tokens + 1,
3281 n_tokens - 1,
3282 &a->mtr.mtr[0]) == 0))
3283 return 0;
3284
3285 tokens += 10;
3286 n_tokens -= 10;
3287
3288 if ((n_tokens == 0) || strcmp(tokens[0], "tc1")) {
3289 a->mtr.tc_mask = 1;
3290 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
3291 return 1 + 10;
3292 }
3293
3294 if ((n_tokens < 30) ||
3295 (parse_table_action_meter_tc(tokens + 1,
3296 n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
3297 strcmp(tokens[10], "tc2") ||
3298 (parse_table_action_meter_tc(tokens + 11,
3299 n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
3300 strcmp(tokens[20], "tc3") ||
3301 (parse_table_action_meter_tc(tokens + 21,
3302 n_tokens - 21, &a->mtr.mtr[3]) == 0))
3303 return 0;
3304
3305 a->mtr.tc_mask = 0xF;
3306 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
3307 return 1 + 10 + 3 * 10;
3308 }
3309
3310 static uint32_t
3311 parse_table_action_tm(char **tokens,
3312 uint32_t n_tokens,
3313 struct table_rule_action *a)
3314 {
3315 uint32_t subport_id, pipe_id;
3316
3317 if ((n_tokens < 5) ||
3318 strcmp(tokens[0], "tm") ||
3319 strcmp(tokens[1], "subport") ||
3320 parser_read_uint32(&subport_id, tokens[2]) ||
3321 strcmp(tokens[3], "pipe") ||
3322 parser_read_uint32(&pipe_id, tokens[4]))
3323 return 0;
3324
3325 a->tm.subport_id = subport_id;
3326 a->tm.pipe_id = pipe_id;
3327 a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
3328 return 5;
3329 }
3330
3331 static uint32_t
3332 parse_table_action_encap(char **tokens,
3333 uint32_t n_tokens,
3334 struct table_rule_action *a)
3335 {
3336 if ((n_tokens == 0) || strcmp(tokens[0], "encap"))
3337 return 0;
3338
3339 tokens++;
3340 n_tokens--;
3341
3342 /* ether */
3343 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
3344 if ((n_tokens < 3) ||
3345 parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
3346 parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
3347 return 0;
3348
3349 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
3350 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3351 return 1 + 3;
3352 }
3353
3354 /* vlan */
3355 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
3356 uint32_t pcp, dei, vid;
3357
3358 if ((n_tokens < 6) ||
3359 parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
3360 parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
3361 parser_read_uint32(&pcp, tokens[3]) ||
3362 (pcp > 0x7) ||
3363 parser_read_uint32(&dei, tokens[4]) ||
3364 (dei > 0x1) ||
3365 parser_read_uint32(&vid, tokens[5]) ||
3366 (vid > 0xFFF))
3367 return 0;
3368
3369 a->encap.vlan.vlan.pcp = pcp & 0x7;
3370 a->encap.vlan.vlan.dei = dei & 0x1;
3371 a->encap.vlan.vlan.vid = vid & 0xFFF;
3372 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
3373 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3374 return 1 + 6;
3375 }
3376
3377 /* qinq */
3378 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
3379 uint32_t svlan_pcp, svlan_dei, svlan_vid;
3380 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
3381
3382 if ((n_tokens < 9) ||
3383 parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
3384 parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
3385 parser_read_uint32(&svlan_pcp, tokens[3]) ||
3386 (svlan_pcp > 0x7) ||
3387 parser_read_uint32(&svlan_dei, tokens[4]) ||
3388 (svlan_dei > 0x1) ||
3389 parser_read_uint32(&svlan_vid, tokens[5]) ||
3390 (svlan_vid > 0xFFF) ||
3391 parser_read_uint32(&cvlan_pcp, tokens[6]) ||
3392 (cvlan_pcp > 0x7) ||
3393 parser_read_uint32(&cvlan_dei, tokens[7]) ||
3394 (cvlan_dei > 0x1) ||
3395 parser_read_uint32(&cvlan_vid, tokens[8]) ||
3396 (cvlan_vid > 0xFFF))
3397 return 0;
3398
3399 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
3400 a->encap.qinq.svlan.dei = svlan_dei & 0x1;
3401 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
3402 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
3403 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
3404 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
3405 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
3406 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3407 return 1 + 9;
3408 }
3409
3410 /* qinq_pppoe */
3411 if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) {
3412 uint32_t svlan_pcp, svlan_dei, svlan_vid;
3413 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
3414
3415 if ((n_tokens < 10) ||
3416 parse_mac_addr(tokens[1],
3417 &a->encap.qinq_pppoe.ether.da) ||
3418 parse_mac_addr(tokens[2],
3419 &a->encap.qinq_pppoe.ether.sa) ||
3420 parser_read_uint32(&svlan_pcp, tokens[3]) ||
3421 (svlan_pcp > 0x7) ||
3422 parser_read_uint32(&svlan_dei, tokens[4]) ||
3423 (svlan_dei > 0x1) ||
3424 parser_read_uint32(&svlan_vid, tokens[5]) ||
3425 (svlan_vid > 0xFFF) ||
3426 parser_read_uint32(&cvlan_pcp, tokens[6]) ||
3427 (cvlan_pcp > 0x7) ||
3428 parser_read_uint32(&cvlan_dei, tokens[7]) ||
3429 (cvlan_dei > 0x1) ||
3430 parser_read_uint32(&cvlan_vid, tokens[8]) ||
3431 (cvlan_vid > 0xFFF) ||
3432 parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id,
3433 tokens[9]))
3434 return 0;
3435
3436 a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7;
3437 a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1;
3438 a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF;
3439 a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7;
3440 a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1;
3441 a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF;
3442 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE;
3443 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3444 return 1 + 10;
3445
3446 }
3447
3448 /* mpls */
3449 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
3450 uint32_t label, tc, ttl;
3451
3452 if (n_tokens < 8)
3453 return 0;
3454
3455 if (strcmp(tokens[1], "unicast") == 0)
3456 a->encap.mpls.unicast = 1;
3457 else if (strcmp(tokens[1], "multicast") == 0)
3458 a->encap.mpls.unicast = 0;
3459 else
3460 return 0;
3461
3462 if (parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
3463 parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
3464 strcmp(tokens[4], "label0") ||
3465 parser_read_uint32(&label, tokens[5]) ||
3466 (label > 0xFFFFF) ||
3467 parser_read_uint32(&tc, tokens[6]) ||
3468 (tc > 0x7) ||
3469 parser_read_uint32(&ttl, tokens[7]) ||
3470 (ttl > 0x3F))
3471 return 0;
3472
3473 a->encap.mpls.mpls[0].label = label;
3474 a->encap.mpls.mpls[0].tc = tc;
3475 a->encap.mpls.mpls[0].ttl = ttl;
3476
3477 tokens += 8;
3478 n_tokens -= 8;
3479
3480 if ((n_tokens == 0) || strcmp(tokens[0], "label1")) {
3481 a->encap.mpls.mpls_count = 1;
3482 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3483 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3484 return 1 + 8;
3485 }
3486
3487 if ((n_tokens < 4) ||
3488 parser_read_uint32(&label, tokens[1]) ||
3489 (label > 0xFFFFF) ||
3490 parser_read_uint32(&tc, tokens[2]) ||
3491 (tc > 0x7) ||
3492 parser_read_uint32(&ttl, tokens[3]) ||
3493 (ttl > 0x3F))
3494 return 0;
3495
3496 a->encap.mpls.mpls[1].label = label;
3497 a->encap.mpls.mpls[1].tc = tc;
3498 a->encap.mpls.mpls[1].ttl = ttl;
3499
3500 tokens += 4;
3501 n_tokens -= 4;
3502
3503 if ((n_tokens == 0) || strcmp(tokens[0], "label2")) {
3504 a->encap.mpls.mpls_count = 2;
3505 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3506 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3507 return 1 + 8 + 4;
3508 }
3509
3510 if ((n_tokens < 4) ||
3511 parser_read_uint32(&label, tokens[1]) ||
3512 (label > 0xFFFFF) ||
3513 parser_read_uint32(&tc, tokens[2]) ||
3514 (tc > 0x7) ||
3515 parser_read_uint32(&ttl, tokens[3]) ||
3516 (ttl > 0x3F))
3517 return 0;
3518
3519 a->encap.mpls.mpls[2].label = label;
3520 a->encap.mpls.mpls[2].tc = tc;
3521 a->encap.mpls.mpls[2].ttl = ttl;
3522
3523 tokens += 4;
3524 n_tokens -= 4;
3525
3526 if ((n_tokens == 0) || strcmp(tokens[0], "label3")) {
3527 a->encap.mpls.mpls_count = 3;
3528 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3529 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3530 return 1 + 8 + 4 + 4;
3531 }
3532
3533 if ((n_tokens < 4) ||
3534 parser_read_uint32(&label, tokens[1]) ||
3535 (label > 0xFFFFF) ||
3536 parser_read_uint32(&tc, tokens[2]) ||
3537 (tc > 0x7) ||
3538 parser_read_uint32(&ttl, tokens[3]) ||
3539 (ttl > 0x3F))
3540 return 0;
3541
3542 a->encap.mpls.mpls[3].label = label;
3543 a->encap.mpls.mpls[3].tc = tc;
3544 a->encap.mpls.mpls[3].ttl = ttl;
3545
3546 a->encap.mpls.mpls_count = 4;
3547 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3548 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3549 return 1 + 8 + 4 + 4 + 4;
3550 }
3551
3552 /* pppoe */
3553 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
3554 if ((n_tokens < 4) ||
3555 parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
3556 parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
3557 parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
3558 tokens[3]))
3559 return 0;
3560
3561 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
3562 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3563 return 1 + 4;
3564 }
3565
3566 /* vxlan */
3567 if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) {
3568 uint32_t n = 0;
3569
3570 n_tokens--;
3571 tokens++;
3572 n++;
3573
3574 /* ether <da> <sa> */
3575 if ((n_tokens < 3) ||
3576 strcmp(tokens[0], "ether") ||
3577 parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) ||
3578 parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa))
3579 return 0;
3580
3581 n_tokens -= 3;
3582 tokens += 3;
3583 n += 3;
3584
3585 /* [vlan <pcp> <dei> <vid>] */
3586 if (strcmp(tokens[0], "vlan") == 0) {
3587 uint32_t pcp, dei, vid;
3588
3589 if ((n_tokens < 4) ||
3590 parser_read_uint32(&pcp, tokens[1]) ||
3591 (pcp > 7) ||
3592 parser_read_uint32(&dei, tokens[2]) ||
3593 (dei > 1) ||
3594 parser_read_uint32(&vid, tokens[3]) ||
3595 (vid > 0xFFF))
3596 return 0;
3597
3598 a->encap.vxlan.vlan.pcp = pcp;
3599 a->encap.vxlan.vlan.dei = dei;
3600 a->encap.vxlan.vlan.vid = vid;
3601
3602 n_tokens -= 4;
3603 tokens += 4;
3604 n += 4;
3605 }
3606
3607 /* ipv4 <sa> <da> <dscp> <ttl>
3608 | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */
3609 if (strcmp(tokens[0], "ipv4") == 0) {
3610 struct in_addr sa, da;
3611 uint8_t dscp, ttl;
3612
3613 if ((n_tokens < 5) ||
3614 parse_ipv4_addr(tokens[1], &sa) ||
3615 parse_ipv4_addr(tokens[2], &da) ||
3616 parser_read_uint8(&dscp, tokens[3]) ||
3617 (dscp > 64) ||
3618 parser_read_uint8(&ttl, tokens[4]))
3619 return 0;
3620
3621 a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr);
3622 a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr);
3623 a->encap.vxlan.ipv4.dscp = dscp;
3624 a->encap.vxlan.ipv4.ttl = ttl;
3625
3626 n_tokens -= 5;
3627 tokens += 5;
3628 n += 5;
3629 } else if (strcmp(tokens[0], "ipv6") == 0) {
3630 struct in6_addr sa, da;
3631 uint32_t flow_label;
3632 uint8_t dscp, hop_limit;
3633
3634 if ((n_tokens < 6) ||
3635 parse_ipv6_addr(tokens[1], &sa) ||
3636 parse_ipv6_addr(tokens[2], &da) ||
3637 parser_read_uint32(&flow_label, tokens[3]) ||
3638 parser_read_uint8(&dscp, tokens[4]) ||
3639 (dscp > 64) ||
3640 parser_read_uint8(&hop_limit, tokens[5]))
3641 return 0;
3642
3643 memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
3644 memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
3645 a->encap.vxlan.ipv6.flow_label = flow_label;
3646 a->encap.vxlan.ipv6.dscp = dscp;
3647 a->encap.vxlan.ipv6.hop_limit = hop_limit;
3648
3649 n_tokens -= 6;
3650 tokens += 6;
3651 n += 6;
3652 } else
3653 return 0;
3654
3655 /* udp <sp> <dp> */
3656 if ((n_tokens < 3) ||
3657 strcmp(tokens[0], "udp") ||
3658 parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) ||
3659 parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2]))
3660 return 0;
3661
3662 n_tokens -= 3;
3663 tokens += 3;
3664 n += 3;
3665
3666 /* vxlan <vni> */
3667 if ((n_tokens < 2) ||
3668 strcmp(tokens[0], "vxlan") ||
3669 parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) ||
3670 (a->encap.vxlan.vxlan.vni > 0xFFFFFF))
3671 return 0;
3672
3673 n_tokens -= 2;
3674 tokens += 2;
3675 n += 2;
3676
3677 a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
3678 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3679 return 1 + n;
3680 }
3681
3682 return 0;
3683 }
3684
3685 static uint32_t
3686 parse_table_action_nat(char **tokens,
3687 uint32_t n_tokens,
3688 struct table_rule_action *a)
3689 {
3690 if ((n_tokens < 4) ||
3691 strcmp(tokens[0], "nat"))
3692 return 0;
3693
3694 if (strcmp(tokens[1], "ipv4") == 0) {
3695 struct in_addr addr;
3696 uint16_t port;
3697
3698 if (parse_ipv4_addr(tokens[2], &addr) ||
3699 parser_read_uint16(&port, tokens[3]))
3700 return 0;
3701
3702 a->nat.ip_version = 1;
3703 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
3704 a->nat.port = port;
3705 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3706 return 4;
3707 }
3708
3709 if (strcmp(tokens[1], "ipv6") == 0) {
3710 struct in6_addr addr;
3711 uint16_t port;
3712
3713 if (parse_ipv6_addr(tokens[2], &addr) ||
3714 parser_read_uint16(&port, tokens[3]))
3715 return 0;
3716
3717 a->nat.ip_version = 0;
3718 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
3719 a->nat.port = port;
3720 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3721 return 4;
3722 }
3723
3724 return 0;
3725 }
3726
3727 static uint32_t
3728 parse_table_action_ttl(char **tokens,
3729 uint32_t n_tokens,
3730 struct table_rule_action *a)
3731 {
3732 if ((n_tokens < 2) ||
3733 strcmp(tokens[0], "ttl"))
3734 return 0;
3735
3736 if (strcmp(tokens[1], "dec") == 0)
3737 a->ttl.decrement = 1;
3738 else if (strcmp(tokens[1], "keep") == 0)
3739 a->ttl.decrement = 0;
3740 else
3741 return 0;
3742
3743 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
3744 return 2;
3745 }
3746
3747 static uint32_t
3748 parse_table_action_stats(char **tokens,
3749 uint32_t n_tokens,
3750 struct table_rule_action *a)
3751 {
3752 if ((n_tokens < 1) ||
3753 strcmp(tokens[0], "stats"))
3754 return 0;
3755
3756 a->stats.n_packets = 0;
3757 a->stats.n_bytes = 0;
3758 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
3759 return 1;
3760 }
3761
3762 static uint32_t
3763 parse_table_action_time(char **tokens,
3764 uint32_t n_tokens,
3765 struct table_rule_action *a)
3766 {
3767 if ((n_tokens < 1) ||
3768 strcmp(tokens[0], "time"))
3769 return 0;
3770
3771 a->time.time = rte_rdtsc();
3772 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
3773 return 1;
3774 }
3775
3776 static void
3777 parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p)
3778 {
3779 struct rte_crypto_sym_xform *xform[2] = {NULL};
3780 uint32_t i;
3781
3782 xform[0] = p->xform;
3783 if (xform[0])
3784 xform[1] = xform[0]->next;
3785
3786 for (i = 0; i < 2; i++) {
3787 if (xform[i] == NULL)
3788 continue;
3789
3790 switch (xform[i]->type) {
3791 case RTE_CRYPTO_SYM_XFORM_CIPHER:
3792 if (p->cipher_auth.cipher_iv.val)
3793 free(p->cipher_auth.cipher_iv.val);
3794 if (p->cipher_auth.cipher_iv_update.val)
3795 free(p->cipher_auth.cipher_iv_update.val);
3796 break;
3797 case RTE_CRYPTO_SYM_XFORM_AUTH:
3798 if (p->cipher_auth.auth_iv.val)
3799 free(p->cipher_auth.cipher_iv.val);
3800 if (p->cipher_auth.auth_iv_update.val)
3801 free(p->cipher_auth.cipher_iv_update.val);
3802 break;
3803 case RTE_CRYPTO_SYM_XFORM_AEAD:
3804 if (p->aead.iv.val)
3805 free(p->aead.iv.val);
3806 if (p->aead.aad.val)
3807 free(p->aead.aad.val);
3808 break;
3809 default:
3810 continue;
3811 }
3812 }
3813
3814 }
3815
3816 static struct rte_crypto_sym_xform *
3817 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p,
3818 uint8_t *key, uint32_t max_key_len, char **tokens,
3819 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
3820 {
3821 struct rte_crypto_sym_xform *xform_cipher;
3822 int status;
3823 size_t len;
3824
3825 if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") ||
3826 strcmp(tokens[3], "cipher_key") ||
3827 strcmp(tokens[5], "cipher_iv"))
3828 return NULL;
3829
3830 xform_cipher = calloc(1, sizeof(*xform_cipher));
3831 if (xform_cipher == NULL)
3832 return NULL;
3833
3834 xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
3835 xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT :
3836 RTE_CRYPTO_CIPHER_OP_DECRYPT;
3837
3838 /* cipher_algo */
3839 status = rte_cryptodev_get_cipher_algo_enum(
3840 &xform_cipher->cipher.algo, tokens[2]);
3841 if (status < 0)
3842 goto error_exit;
3843
3844 /* cipher_key */
3845 len = strlen(tokens[4]);
3846 if (len / 2 > max_key_len) {
3847 status = -ENOMEM;
3848 goto error_exit;
3849 }
3850
3851 status = parse_hex_string(tokens[4], key, (uint32_t *)&len);
3852 if (status < 0)
3853 goto error_exit;
3854
3855 xform_cipher->cipher.key.data = key;
3856 xform_cipher->cipher.key.length = (uint16_t)len;
3857
3858 /* cipher_iv */
3859 len = strlen(tokens[6]);
3860
3861 p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1);
3862 if (p->cipher_auth.cipher_iv.val == NULL)
3863 goto error_exit;
3864
3865 status = parse_hex_string(tokens[6],
3866 p->cipher_auth.cipher_iv.val,
3867 (uint32_t *)&len);
3868 if (status < 0)
3869 goto error_exit;
3870
3871 xform_cipher->cipher.iv.length = (uint16_t)len;
3872 xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
3873 p->cipher_auth.cipher_iv.length = (uint32_t)len;
3874 *used_n_tokens = 7;
3875
3876 return xform_cipher;
3877
3878 error_exit:
3879 if (p->cipher_auth.cipher_iv.val) {
3880 free(p->cipher_auth.cipher_iv.val);
3881 p->cipher_auth.cipher_iv.val = NULL;
3882 }
3883
3884 free(xform_cipher);
3885
3886 return NULL;
3887 }
3888
3889 static struct rte_crypto_sym_xform *
3890 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p,
3891 uint8_t *key, uint32_t max_key_len, char **tokens,
3892 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
3893 {
3894 struct rte_crypto_sym_xform *xform_cipher;
3895 struct rte_crypto_sym_xform *xform_auth;
3896 int status;
3897 size_t len;
3898
3899 if (n_tokens < 13 ||
3900 strcmp(tokens[7], "auth_algo") ||
3901 strcmp(tokens[9], "auth_key") ||
3902 strcmp(tokens[11], "digest_size"))
3903 return NULL;
3904
3905 xform_auth = calloc(1, sizeof(*xform_auth));
3906 if (xform_auth == NULL)
3907 return NULL;
3908
3909 xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH;
3910 xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE :
3911 RTE_CRYPTO_AUTH_OP_VERIFY;
3912
3913 /* auth_algo */
3914 status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo,
3915 tokens[8]);
3916 if (status < 0)
3917 goto error_exit;
3918
3919 /* auth_key */
3920 len = strlen(tokens[10]);
3921 if (len / 2 > max_key_len) {
3922 status = -ENOMEM;
3923 goto error_exit;
3924 }
3925
3926 status = parse_hex_string(tokens[10], key, (uint32_t *)&len);
3927 if (status < 0)
3928 goto error_exit;
3929
3930 xform_auth->auth.key.data = key;
3931 xform_auth->auth.key.length = (uint16_t)len;
3932
3933 key += xform_auth->auth.key.length;
3934 max_key_len -= xform_auth->auth.key.length;
3935
3936 if (strcmp(tokens[11], "digest_size"))
3937 goto error_exit;
3938
3939 status = parser_read_uint16(&xform_auth->auth.digest_length,
3940 tokens[12]);
3941 if (status < 0)
3942 goto error_exit;
3943
3944 xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens,
3945 7, encrypt, used_n_tokens);
3946 if (xform_cipher == NULL)
3947 goto error_exit;
3948
3949 *used_n_tokens += 6;
3950
3951 if (encrypt) {
3952 xform_cipher->next = xform_auth;
3953 return xform_cipher;
3954 } else {
3955 xform_auth->next = xform_cipher;
3956 return xform_auth;
3957 }
3958
3959 error_exit:
3960 if (p->cipher_auth.auth_iv.val) {
3961 free(p->cipher_auth.auth_iv.val);
3962 p->cipher_auth.auth_iv.val = 0;
3963 }
3964
3965 free(xform_auth);
3966
3967 return NULL;
3968 }
3969
3970 static struct rte_crypto_sym_xform *
3971 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p,
3972 uint8_t *key, uint32_t max_key_len, char **tokens,
3973 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens)
3974 {
3975 struct rte_crypto_sym_xform *xform_aead;
3976 int status;
3977 size_t len;
3978
3979 if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") ||
3980 strcmp(tokens[3], "aead_key") ||
3981 strcmp(tokens[5], "aead_iv") ||
3982 strcmp(tokens[7], "aead_aad") ||
3983 strcmp(tokens[9], "digest_size"))
3984 return NULL;
3985
3986 xform_aead = calloc(1, sizeof(*xform_aead));
3987 if (xform_aead == NULL)
3988 return NULL;
3989
3990 xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD;
3991 xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT :
3992 RTE_CRYPTO_AEAD_OP_DECRYPT;
3993
3994 /* aead_algo */
3995 status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo,
3996 tokens[2]);
3997 if (status < 0)
3998 goto error_exit;
3999
4000 /* aead_key */
4001 len = strlen(tokens[4]);
4002 if (len / 2 > max_key_len) {
4003 status = -ENOMEM;
4004 goto error_exit;
4005 }
4006
4007 status = parse_hex_string(tokens[4], key, (uint32_t *)&len);
4008 if (status < 0)
4009 goto error_exit;
4010
4011 xform_aead->aead.key.data = key;
4012 xform_aead->aead.key.length = (uint16_t)len;
4013
4014 /* aead_iv */
4015 len = strlen(tokens[6]);
4016 p->aead.iv.val = calloc(1, len / 2 + 1);
4017 if (p->aead.iv.val == NULL)
4018 goto error_exit;
4019
4020 status = parse_hex_string(tokens[6], p->aead.iv.val,
4021 (uint32_t *)&len);
4022 if (status < 0)
4023 goto error_exit;
4024
4025 xform_aead->aead.iv.length = (uint16_t)len;
4026 xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET;
4027 p->aead.iv.length = (uint32_t)len;
4028
4029 /* aead_aad */
4030 len = strlen(tokens[8]);
4031 p->aead.aad.val = calloc(1, len / 2 + 1);
4032 if (p->aead.aad.val == NULL)
4033 goto error_exit;
4034
4035 status = parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len);
4036 if (status < 0)
4037 goto error_exit;
4038
4039 xform_aead->aead.aad_length = (uint16_t)len;
4040 p->aead.aad.length = (uint32_t)len;
4041
4042 /* digest_size */
4043 status = parser_read_uint16(&xform_aead->aead.digest_length,
4044 tokens[10]);
4045 if (status < 0)
4046 goto error_exit;
4047
4048 *used_n_tokens = 11;
4049
4050 return xform_aead;
4051
4052 error_exit:
4053 if (p->aead.iv.val) {
4054 free(p->aead.iv.val);
4055 p->aead.iv.val = NULL;
4056 }
4057 if (p->aead.aad.val) {
4058 free(p->aead.aad.val);
4059 p->aead.aad.val = NULL;
4060 }
4061
4062 free(xform_aead);
4063
4064 return NULL;
4065 }
4066
4067
4068 static uint32_t
4069 parse_table_action_sym_crypto(char **tokens,
4070 uint32_t n_tokens,
4071 struct table_rule_action *a)
4072 {
4073 struct rte_table_action_sym_crypto_params *p = &a->sym_crypto;
4074 struct rte_crypto_sym_xform *xform = NULL;
4075 uint8_t *key = a->sym_crypto_key;
4076 uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE;
4077 uint32_t used_n_tokens;
4078 uint32_t encrypt;
4079 int status;
4080
4081 if ((n_tokens < 12) ||
4082 strcmp(tokens[0], "sym_crypto") ||
4083 strcmp(tokens[2], "type"))
4084 return 0;
4085
4086 memset(p, 0, sizeof(*p));
4087
4088 if (strcmp(tokens[1], "encrypt") == 0)
4089 encrypt = 1;
4090 else
4091 encrypt = 0;
4092
4093 status = parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]);
4094 if (status < 0)
4095 return 0;
4096
4097 if (strcmp(tokens[3], "cipher") == 0) {
4098 tokens += 3;
4099 n_tokens -= 3;
4100
4101 xform = parse_table_action_cipher(p, key, max_key_len, tokens,
4102 n_tokens, encrypt, &used_n_tokens);
4103 } else if (strcmp(tokens[3], "cipher_auth") == 0) {
4104 tokens += 3;
4105 n_tokens -= 3;
4106
4107 xform = parse_table_action_cipher_auth(p, key, max_key_len,
4108 tokens, n_tokens, encrypt, &used_n_tokens);
4109 } else if (strcmp(tokens[3], "aead") == 0) {
4110 tokens += 3;
4111 n_tokens -= 3;
4112
4113 xform = parse_table_action_aead(p, key, max_key_len, tokens,
4114 n_tokens, encrypt, &used_n_tokens);
4115 }
4116
4117 if (xform == NULL)
4118 return 0;
4119
4120 p->xform = xform;
4121
4122 if (strcmp(tokens[used_n_tokens], "data_offset")) {
4123 parse_free_sym_crypto_param_data(p);
4124 return 0;
4125 }
4126
4127 a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO;
4128
4129 return used_n_tokens + 5;
4130 }
4131
4132 static uint32_t
4133 parse_table_action_tag(char **tokens,
4134 uint32_t n_tokens,
4135 struct table_rule_action *a)
4136 {
4137 if ((n_tokens < 2) ||
4138 strcmp(tokens[0], "tag"))
4139 return 0;
4140
4141 if (parser_read_uint32(&a->tag.tag, tokens[1]))
4142 return 0;
4143
4144 a->action_mask |= 1 << RTE_TABLE_ACTION_TAG;
4145 return 2;
4146 }
4147
4148 static uint32_t
4149 parse_table_action_decap(char **tokens,
4150 uint32_t n_tokens,
4151 struct table_rule_action *a)
4152 {
4153 if ((n_tokens < 2) ||
4154 strcmp(tokens[0], "decap"))
4155 return 0;
4156
4157 if (parser_read_uint16(&a->decap.n, tokens[1]))
4158 return 0;
4159
4160 a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP;
4161 return 2;
4162 }
4163
4164 static uint32_t
4165 parse_table_action(char **tokens,
4166 uint32_t n_tokens,
4167 char *out,
4168 size_t out_size,
4169 struct table_rule_action *a)
4170 {
4171 uint32_t n_tokens0 = n_tokens;
4172
4173 memset(a, 0, sizeof(*a));
4174
4175 if ((n_tokens < 2) ||
4176 strcmp(tokens[0], "action"))
4177 return 0;
4178
4179 tokens++;
4180 n_tokens--;
4181
4182 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
4183 uint32_t n;
4184
4185 n = parse_table_action_fwd(tokens, n_tokens, a);
4186 if (n == 0) {
4187 snprintf(out, out_size, MSG_ARG_INVALID,
4188 "action fwd");
4189 return 0;
4190 }
4191
4192 tokens += n;
4193 n_tokens -= n;
4194 }
4195
4196 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
4197 uint32_t n;
4198
4199 n = parse_table_action_balance(tokens, n_tokens, a);
4200 if (n == 0) {
4201 snprintf(out, out_size, MSG_ARG_INVALID,
4202 "action balance");
4203 return 0;
4204 }
4205
4206 tokens += n;
4207 n_tokens -= n;
4208 }
4209
4210 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
4211 uint32_t n;
4212
4213 n = parse_table_action_meter(tokens, n_tokens, a);
4214 if (n == 0) {
4215 snprintf(out, out_size, MSG_ARG_INVALID,
4216 "action meter");
4217 return 0;
4218 }
4219
4220 tokens += n;
4221 n_tokens -= n;
4222 }
4223
4224 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
4225 uint32_t n;
4226
4227 n = parse_table_action_tm(tokens, n_tokens, a);
4228 if (n == 0) {
4229 snprintf(out, out_size, MSG_ARG_INVALID,
4230 "action tm");
4231 return 0;
4232 }
4233
4234 tokens += n;
4235 n_tokens -= n;
4236 }
4237
4238 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
4239 uint32_t n;
4240
4241 n = parse_table_action_encap(tokens, n_tokens, a);
4242 if (n == 0) {
4243 snprintf(out, out_size, MSG_ARG_INVALID,
4244 "action encap");
4245 return 0;
4246 }
4247
4248 tokens += n;
4249 n_tokens -= n;
4250 }
4251
4252 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
4253 uint32_t n;
4254
4255 n = parse_table_action_nat(tokens, n_tokens, a);
4256 if (n == 0) {
4257 snprintf(out, out_size, MSG_ARG_INVALID,
4258 "action nat");
4259 return 0;
4260 }
4261
4262 tokens += n;
4263 n_tokens -= n;
4264 }
4265
4266 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
4267 uint32_t n;
4268
4269 n = parse_table_action_ttl(tokens, n_tokens, a);
4270 if (n == 0) {
4271 snprintf(out, out_size, MSG_ARG_INVALID,
4272 "action ttl");
4273 return 0;
4274 }
4275
4276 tokens += n;
4277 n_tokens -= n;
4278 }
4279
4280 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
4281 uint32_t n;
4282
4283 n = parse_table_action_stats(tokens, n_tokens, a);
4284 if (n == 0) {
4285 snprintf(out, out_size, MSG_ARG_INVALID,
4286 "action stats");
4287 return 0;
4288 }
4289
4290 tokens += n;
4291 n_tokens -= n;
4292 }
4293
4294 if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
4295 uint32_t n;
4296
4297 n = parse_table_action_time(tokens, n_tokens, a);
4298 if (n == 0) {
4299 snprintf(out, out_size, MSG_ARG_INVALID,
4300 "action time");
4301 return 0;
4302 }
4303
4304 tokens += n;
4305 n_tokens -= n;
4306 }
4307
4308 if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) {
4309 uint32_t n;
4310
4311 n = parse_table_action_sym_crypto(tokens, n_tokens, a);
4312 if (n == 0) {
4313 snprintf(out, out_size, MSG_ARG_INVALID,
4314 "action sym_crypto");
4315 }
4316
4317 tokens += n;
4318 n_tokens -= n;
4319 }
4320
4321 if (n_tokens && (strcmp(tokens[0], "tag") == 0)) {
4322 uint32_t n;
4323
4324 n = parse_table_action_tag(tokens, n_tokens, a);
4325 if (n == 0) {
4326 snprintf(out, out_size, MSG_ARG_INVALID,
4327 "action tag");
4328 return 0;
4329 }
4330
4331 tokens += n;
4332 n_tokens -= n;
4333 }
4334
4335 if (n_tokens && (strcmp(tokens[0], "decap") == 0)) {
4336 uint32_t n;
4337
4338 n = parse_table_action_decap(tokens, n_tokens, a);
4339 if (n == 0) {
4340 snprintf(out, out_size, MSG_ARG_INVALID,
4341 "action decap");
4342 return 0;
4343 }
4344
4345 tokens += n;
4346 n_tokens -= n;
4347 }
4348
4349 if (n_tokens0 - n_tokens == 1) {
4350 snprintf(out, out_size, MSG_ARG_INVALID, "action");
4351 return 0;
4352 }
4353
4354 return n_tokens0 - n_tokens;
4355 }
4356
4357
4358 static const char cmd_pipeline_table_rule_add_help[] =
4359 "pipeline <pipeline_name> table <table_id> rule add\n"
4360 " match <match>\n"
4361 " action <table_action>\n";
4362
4363 static void
4364 cmd_pipeline_table_rule_add(char **tokens,
4365 uint32_t n_tokens,
4366 char *out,
4367 size_t out_size)
4368 {
4369 struct table_rule_match m;
4370 struct table_rule_action a;
4371 char *pipeline_name;
4372 uint32_t table_id, t0, n_tokens_parsed;
4373 int status;
4374
4375 if (n_tokens < 8) {
4376 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4377 return;
4378 }
4379
4380 pipeline_name = tokens[1];
4381
4382 if (strcmp(tokens[2], "table") != 0) {
4383 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4384 return;
4385 }
4386
4387 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4388 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4389 return;
4390 }
4391
4392 if (strcmp(tokens[4], "rule") != 0) {
4393 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4394 return;
4395 }
4396
4397 if (strcmp(tokens[5], "add") != 0) {
4398 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
4399 return;
4400 }
4401
4402 t0 = 6;
4403
4404 /* match */
4405 n_tokens_parsed = parse_match(tokens + t0,
4406 n_tokens - t0,
4407 out,
4408 out_size,
4409 &m);
4410 if (n_tokens_parsed == 0)
4411 return;
4412 t0 += n_tokens_parsed;
4413
4414 /* action */
4415 n_tokens_parsed = parse_table_action(tokens + t0,
4416 n_tokens - t0,
4417 out,
4418 out_size,
4419 &a);
4420 if (n_tokens_parsed == 0)
4421 return;
4422 t0 += n_tokens_parsed;
4423
4424 if (t0 != n_tokens) {
4425 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
4426 return;
4427 }
4428
4429 status = pipeline_table_rule_add(pipeline_name, table_id, &m, &a);
4430 if (status) {
4431 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4432 return;
4433 }
4434
4435 if (a.action_mask & 1 << RTE_TABLE_ACTION_SYM_CRYPTO)
4436 parse_free_sym_crypto_param_data(&a.sym_crypto);
4437 }
4438
4439
4440 static const char cmd_pipeline_table_rule_add_default_help[] =
4441 "pipeline <pipeline_name> table <table_id> rule add\n"
4442 " match\n"
4443 " default\n"
4444 " action\n"
4445 " fwd\n"
4446 " drop\n"
4447 " | port <port_id>\n"
4448 " | meta\n"
4449 " | table <table_id>\n";
4450
4451 static void
4452 cmd_pipeline_table_rule_add_default(char **tokens,
4453 uint32_t n_tokens,
4454 char *out,
4455 size_t out_size)
4456 {
4457 struct table_rule_action action;
4458 char *pipeline_name;
4459 uint32_t table_id;
4460 int status;
4461
4462 if ((n_tokens != 11) && (n_tokens != 12)) {
4463 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4464 return;
4465 }
4466
4467 pipeline_name = tokens[1];
4468
4469 if (strcmp(tokens[2], "table") != 0) {
4470 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4471 return;
4472 }
4473
4474 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4475 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4476 return;
4477 }
4478
4479 if (strcmp(tokens[4], "rule") != 0) {
4480 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4481 return;
4482 }
4483
4484 if (strcmp(tokens[5], "add") != 0) {
4485 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
4486 return;
4487 }
4488
4489 if (strcmp(tokens[6], "match") != 0) {
4490 snprintf(out, out_size, MSG_ARG_INVALID, "match");
4491 return;
4492 }
4493
4494 if (strcmp(tokens[7], "default") != 0) {
4495 snprintf(out, out_size, MSG_ARG_INVALID, "default");
4496 return;
4497 }
4498
4499 if (strcmp(tokens[8], "action") != 0) {
4500 snprintf(out, out_size, MSG_ARG_INVALID, "action");
4501 return;
4502 }
4503
4504 if (strcmp(tokens[9], "fwd") != 0) {
4505 snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
4506 return;
4507 }
4508
4509 action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
4510
4511 if (strcmp(tokens[10], "drop") == 0) {
4512 if (n_tokens != 11) {
4513 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4514 return;
4515 }
4516
4517 action.fwd.action = RTE_PIPELINE_ACTION_DROP;
4518 } else if (strcmp(tokens[10], "port") == 0) {
4519 uint32_t id;
4520
4521 if (n_tokens != 12) {
4522 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4523 return;
4524 }
4525
4526 if (parser_read_uint32(&id, tokens[11]) != 0) {
4527 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
4528 return;
4529 }
4530
4531 action.fwd.action = RTE_PIPELINE_ACTION_PORT;
4532 action.fwd.id = id;
4533 } else if (strcmp(tokens[10], "meta") == 0) {
4534 if (n_tokens != 11) {
4535 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4536 return;
4537 }
4538
4539 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
4540 } else if (strcmp(tokens[10], "table") == 0) {
4541 uint32_t id;
4542
4543 if (n_tokens != 12) {
4544 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4545 return;
4546 }
4547
4548 if (parser_read_uint32(&id, tokens[11]) != 0) {
4549 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4550 return;
4551 }
4552
4553 action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
4554 action.fwd.id = id;
4555 } else {
4556 snprintf(out, out_size, MSG_ARG_INVALID,
4557 "drop or port or meta or table");
4558 return;
4559 }
4560
4561 status = pipeline_table_rule_add_default(pipeline_name,
4562 table_id,
4563 &action);
4564 if (status) {
4565 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4566 return;
4567 }
4568 }
4569
4570
4571 static const char cmd_pipeline_table_rule_add_bulk_help[] =
4572 "pipeline <pipeline_name> table <table_id> rule add bulk <file_name>\n"
4573 "\n"
4574 " File <file_name>:\n"
4575 " - line format: match <match> action <action>\n";
4576
4577 static int
4578 cli_rule_file_process(const char *file_name,
4579 size_t line_len_max,
4580 struct table_rule_list **rule_list,
4581 uint32_t *n_rules,
4582 uint32_t *line_number,
4583 char *out,
4584 size_t out_size);
4585
4586 static void
4587 cmd_pipeline_table_rule_add_bulk(char **tokens,
4588 uint32_t n_tokens,
4589 char *out,
4590 size_t out_size)
4591 {
4592 struct table_rule_list *list = NULL;
4593 char *pipeline_name, *file_name;
4594 uint32_t table_id, n_rules, n_rules_added, n_rules_not_added, line_number;
4595 int status;
4596
4597 if (n_tokens != 8) {
4598 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4599 return;
4600 }
4601
4602 pipeline_name = tokens[1];
4603
4604 if (strcmp(tokens[2], "table") != 0) {
4605 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4606 return;
4607 }
4608
4609 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4610 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4611 return;
4612 }
4613
4614 if (strcmp(tokens[4], "rule") != 0) {
4615 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4616 return;
4617 }
4618
4619 if (strcmp(tokens[5], "add") != 0) {
4620 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
4621 return;
4622 }
4623
4624 if (strcmp(tokens[6], "bulk") != 0) {
4625 snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
4626 return;
4627 }
4628
4629 file_name = tokens[7];
4630
4631 /* Load rules from file. */
4632 status = cli_rule_file_process(file_name,
4633 1024,
4634 &list,
4635 &n_rules,
4636 &line_number,
4637 out,
4638 out_size);
4639 if (status) {
4640 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
4641 return;
4642 }
4643
4644 /* Rule bulk add */
4645 status = pipeline_table_rule_add_bulk(pipeline_name,
4646 table_id,
4647 list,
4648 &n_rules_added,
4649 &n_rules_not_added);
4650 if (status) {
4651 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4652 return;
4653 }
4654
4655 snprintf(out, out_size, "Added %u rules out of %u.\n",
4656 n_rules_added,
4657 n_rules);
4658 }
4659
4660
4661 static const char cmd_pipeline_table_rule_delete_help[] =
4662 "pipeline <pipeline_name> table <table_id> rule delete\n"
4663 " match <match>\n";
4664
4665 static void
4666 cmd_pipeline_table_rule_delete(char **tokens,
4667 uint32_t n_tokens,
4668 char *out,
4669 size_t out_size)
4670 {
4671 struct table_rule_match m;
4672 char *pipeline_name;
4673 uint32_t table_id, n_tokens_parsed, t0;
4674 int status;
4675
4676 if (n_tokens < 8) {
4677 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4678 return;
4679 }
4680
4681 pipeline_name = tokens[1];
4682
4683 if (strcmp(tokens[2], "table") != 0) {
4684 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4685 return;
4686 }
4687
4688 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4689 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4690 return;
4691 }
4692
4693 if (strcmp(tokens[4], "rule") != 0) {
4694 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4695 return;
4696 }
4697
4698 if (strcmp(tokens[5], "delete") != 0) {
4699 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4700 return;
4701 }
4702
4703 t0 = 6;
4704
4705 /* match */
4706 n_tokens_parsed = parse_match(tokens + t0,
4707 n_tokens - t0,
4708 out,
4709 out_size,
4710 &m);
4711 if (n_tokens_parsed == 0)
4712 return;
4713 t0 += n_tokens_parsed;
4714
4715 if (n_tokens != t0) {
4716 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4717 return;
4718 }
4719
4720 status = pipeline_table_rule_delete(pipeline_name,
4721 table_id,
4722 &m);
4723 if (status) {
4724 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4725 return;
4726 }
4727 }
4728
4729
4730 static const char cmd_pipeline_table_rule_delete_default_help[] =
4731 "pipeline <pipeline_name> table <table_id> rule delete\n"
4732 " match\n"
4733 " default\n";
4734
4735 static void
4736 cmd_pipeline_table_rule_delete_default(char **tokens,
4737 uint32_t n_tokens,
4738 char *out,
4739 size_t out_size)
4740 {
4741 char *pipeline_name;
4742 uint32_t table_id;
4743 int status;
4744
4745 if (n_tokens != 8) {
4746 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4747 return;
4748 }
4749
4750 pipeline_name = tokens[1];
4751
4752 if (strcmp(tokens[2], "table") != 0) {
4753 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4754 return;
4755 }
4756
4757 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4758 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4759 return;
4760 }
4761
4762 if (strcmp(tokens[4], "rule") != 0) {
4763 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4764 return;
4765 }
4766
4767 if (strcmp(tokens[5], "delete") != 0) {
4768 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4769 return;
4770 }
4771
4772 if (strcmp(tokens[6], "match") != 0) {
4773 snprintf(out, out_size, MSG_ARG_INVALID, "match");
4774 return;
4775 }
4776
4777 if (strcmp(tokens[7], "default") != 0) {
4778 snprintf(out, out_size, MSG_ARG_INVALID, "default");
4779 return;
4780 }
4781
4782 status = pipeline_table_rule_delete_default(pipeline_name,
4783 table_id);
4784 if (status) {
4785 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4786 return;
4787 }
4788 }
4789
4790 static void
4791 ether_addr_show(FILE *f, struct rte_ether_addr *addr)
4792 {
4793 fprintf(f, "%02x:%02x:%02x:%02x:%02x:%02x",
4794 (uint32_t)addr->addr_bytes[0], (uint32_t)addr->addr_bytes[1],
4795 (uint32_t)addr->addr_bytes[2], (uint32_t)addr->addr_bytes[3],
4796 (uint32_t)addr->addr_bytes[4], (uint32_t)addr->addr_bytes[5]);
4797 }
4798
4799 static void
4800 ipv4_addr_show(FILE *f, uint32_t addr)
4801 {
4802 fprintf(f, "%u.%u.%u.%u",
4803 addr >> 24,
4804 (addr >> 16) & 0xFF,
4805 (addr >> 8) & 0xFF,
4806 addr & 0xFF);
4807 }
4808
4809 static void
4810 ipv6_addr_show(FILE *f, uint8_t *addr)
4811 {
4812 fprintf(f, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:"
4813 "%02x%02x:%02x%02x:%02x%02x:%02x%02x:",
4814 (uint32_t)addr[0], (uint32_t)addr[1],
4815 (uint32_t)addr[2], (uint32_t)addr[3],
4816 (uint32_t)addr[4], (uint32_t)addr[5],
4817 (uint32_t)addr[6], (uint32_t)addr[7],
4818 (uint32_t)addr[8], (uint32_t)addr[9],
4819 (uint32_t)addr[10], (uint32_t)addr[11],
4820 (uint32_t)addr[12], (uint32_t)addr[13],
4821 (uint32_t)addr[14], (uint32_t)addr[15]);
4822 }
4823
4824 static const char *
4825 policer_action_string(enum rte_table_action_policer action) {
4826 switch (action) {
4827 case RTE_TABLE_ACTION_POLICER_COLOR_GREEN: return "G";
4828 case RTE_TABLE_ACTION_POLICER_COLOR_YELLOW: return "Y";
4829 case RTE_TABLE_ACTION_POLICER_COLOR_RED: return "R";
4830 case RTE_TABLE_ACTION_POLICER_DROP: return "D";
4831 default: return "?";
4832 }
4833 }
4834
4835 static int
4836 table_rule_show(const char *pipeline_name,
4837 uint32_t table_id,
4838 const char *file_name)
4839 {
4840 struct pipeline *p;
4841 struct table *table;
4842 struct table_rule *rule;
4843 FILE *f = NULL;
4844 uint32_t i;
4845
4846 /* Check input params. */
4847 if ((pipeline_name == NULL) ||
4848 (file_name == NULL))
4849 return -1;
4850
4851 p = pipeline_find(pipeline_name);
4852 if ((p == NULL) ||
4853 (table_id >= p->n_tables))
4854 return -1;
4855
4856 table = &p->table[table_id];
4857
4858 /* Open file. */
4859 f = fopen(file_name, "w");
4860 if (f == NULL)
4861 return -1;
4862
4863 /* Write table rules to file. */
4864 TAILQ_FOREACH(rule, &table->rules, node) {
4865 struct table_rule_match *m = &rule->match;
4866 struct table_rule_action *a = &rule->action;
4867
4868 fprintf(f, "match ");
4869 switch (m->match_type) {
4870 case TABLE_ACL:
4871 fprintf(f, "acl priority %u ",
4872 m->match.acl.priority);
4873
4874 fprintf(f, m->match.acl.ip_version ? "ipv4 " : "ipv6 ");
4875
4876 if (m->match.acl.ip_version)
4877 ipv4_addr_show(f, m->match.acl.ipv4.sa);
4878 else
4879 ipv6_addr_show(f, m->match.acl.ipv6.sa);
4880
4881 fprintf(f, "%u", m->match.acl.sa_depth);
4882
4883 if (m->match.acl.ip_version)
4884 ipv4_addr_show(f, m->match.acl.ipv4.da);
4885 else
4886 ipv6_addr_show(f, m->match.acl.ipv6.da);
4887
4888 fprintf(f, "%u", m->match.acl.da_depth);
4889
4890 fprintf(f, "%u %u %u %u %u ",
4891 (uint32_t)m->match.acl.sp0,
4892 (uint32_t)m->match.acl.sp1,
4893 (uint32_t)m->match.acl.dp0,
4894 (uint32_t)m->match.acl.dp1,
4895 (uint32_t)m->match.acl.proto);
4896 break;
4897
4898 case TABLE_ARRAY:
4899 fprintf(f, "array %u ",
4900 m->match.array.pos);
4901 break;
4902
4903 case TABLE_HASH:
4904 fprintf(f, "hash raw ");
4905 for (i = 0; i < table->params.match.hash.key_size; i++)
4906 fprintf(f, "%02x", m->match.hash.key[i]);
4907 fprintf(f, " ");
4908 break;
4909
4910 case TABLE_LPM:
4911 fprintf(f, "lpm ");
4912
4913 fprintf(f, m->match.lpm.ip_version ? "ipv4 " : "ipv6 ");
4914
4915 if (m->match.acl.ip_version)
4916 ipv4_addr_show(f, m->match.lpm.ipv4);
4917 else
4918 ipv6_addr_show(f, m->match.lpm.ipv6);
4919
4920 fprintf(f, "%u ",
4921 (uint32_t)m->match.lpm.depth);
4922 break;
4923
4924 default:
4925 fprintf(f, "unknown ");
4926 }
4927
4928 fprintf(f, "action ");
4929 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) {
4930 fprintf(f, "fwd ");
4931 switch (a->fwd.action) {
4932 case RTE_PIPELINE_ACTION_DROP:
4933 fprintf(f, "drop ");
4934 break;
4935
4936 case RTE_PIPELINE_ACTION_PORT:
4937 fprintf(f, "port %u ", a->fwd.id);
4938 break;
4939
4940 case RTE_PIPELINE_ACTION_PORT_META:
4941 fprintf(f, "meta ");
4942 break;
4943
4944 case RTE_PIPELINE_ACTION_TABLE:
4945 default:
4946 fprintf(f, "table %u ", a->fwd.id);
4947 }
4948 }
4949
4950 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) {
4951 fprintf(f, "balance ");
4952 for (i = 0; i < RTE_DIM(a->lb.out); i++)
4953 fprintf(f, "%u ", a->lb.out[i]);
4954 }
4955
4956 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) {
4957 fprintf(f, "mtr ");
4958 for (i = 0; i < RTE_TABLE_ACTION_TC_MAX; i++)
4959 if (a->mtr.tc_mask & (1 << i)) {
4960 struct rte_table_action_mtr_tc_params *p =
4961 &a->mtr.mtr[i];
4962 enum rte_table_action_policer ga =
4963 p->policer[RTE_COLOR_GREEN];
4964 enum rte_table_action_policer ya =
4965 p->policer[RTE_COLOR_YELLOW];
4966 enum rte_table_action_policer ra =
4967 p->policer[RTE_COLOR_RED];
4968
4969 fprintf(f, "tc%u meter %u policer g %s y %s r %s ",
4970 i,
4971 a->mtr.mtr[i].meter_profile_id,
4972 policer_action_string(ga),
4973 policer_action_string(ya),
4974 policer_action_string(ra));
4975 }
4976 }
4977
4978 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TM))
4979 fprintf(f, "tm subport %u pipe %u ",
4980 a->tm.subport_id,
4981 a->tm.pipe_id);
4982
4983 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) {
4984 fprintf(f, "encap ");
4985 switch (a->encap.type) {
4986 case RTE_TABLE_ACTION_ENCAP_ETHER:
4987 fprintf(f, "ether ");
4988 ether_addr_show(f, &a->encap.ether.ether.da);
4989 fprintf(f, " ");
4990 ether_addr_show(f, &a->encap.ether.ether.sa);
4991 fprintf(f, " ");
4992 break;
4993
4994 case RTE_TABLE_ACTION_ENCAP_VLAN:
4995 fprintf(f, "vlan ");
4996 ether_addr_show(f, &a->encap.vlan.ether.da);
4997 fprintf(f, " ");
4998 ether_addr_show(f, &a->encap.vlan.ether.sa);
4999 fprintf(f, " pcp %u dei %u vid %u ",
5000 a->encap.vlan.vlan.pcp,
5001 a->encap.vlan.vlan.dei,
5002 a->encap.vlan.vlan.vid);
5003 break;
5004
5005 case RTE_TABLE_ACTION_ENCAP_QINQ:
5006 fprintf(f, "qinq ");
5007 ether_addr_show(f, &a->encap.qinq.ether.da);
5008 fprintf(f, " ");
5009 ether_addr_show(f, &a->encap.qinq.ether.sa);
5010 fprintf(f, " pcp %u dei %u vid %u pcp %u dei %u vid %u ",
5011 a->encap.qinq.svlan.pcp,
5012 a->encap.qinq.svlan.dei,
5013 a->encap.qinq.svlan.vid,
5014 a->encap.qinq.cvlan.pcp,
5015 a->encap.qinq.cvlan.dei,
5016 a->encap.qinq.cvlan.vid);
5017 break;
5018
5019 case RTE_TABLE_ACTION_ENCAP_MPLS:
5020 fprintf(f, "mpls %s ", (a->encap.mpls.unicast) ?
5021 "unicast " : "multicast ");
5022 ether_addr_show(f, &a->encap.mpls.ether.da);
5023 fprintf(f, " ");
5024 ether_addr_show(f, &a->encap.mpls.ether.sa);
5025 fprintf(f, " ");
5026 for (i = 0; i < a->encap.mpls.mpls_count; i++) {
5027 struct rte_table_action_mpls_hdr *l =
5028 &a->encap.mpls.mpls[i];
5029
5030 fprintf(f, "label%u %u %u %u ",
5031 i,
5032 l->label,
5033 l->tc,
5034 l->ttl);
5035 }
5036 break;
5037
5038 case RTE_TABLE_ACTION_ENCAP_PPPOE:
5039 fprintf(f, "pppoe ");
5040 ether_addr_show(f, &a->encap.pppoe.ether.da);
5041 fprintf(f, " ");
5042 ether_addr_show(f, &a->encap.pppoe.ether.sa);
5043 fprintf(f, " %u ", a->encap.pppoe.pppoe.session_id);
5044 break;
5045
5046 case RTE_TABLE_ACTION_ENCAP_VXLAN:
5047 fprintf(f, "vxlan ether ");
5048 ether_addr_show(f, &a->encap.vxlan.ether.da);
5049 fprintf(f, " ");
5050 ether_addr_show(f, &a->encap.vxlan.ether.sa);
5051 if (table->ap->params.encap.vxlan.vlan)
5052 fprintf(f, " vlan pcp %u dei %u vid %u ",
5053 a->encap.vxlan.vlan.pcp,
5054 a->encap.vxlan.vlan.dei,
5055 a->encap.vxlan.vlan.vid);
5056 if (table->ap->params.encap.vxlan.ip_version) {
5057 fprintf(f, " ipv4 ");
5058 ipv4_addr_show(f, a->encap.vxlan.ipv4.sa);
5059 fprintf(f, " ");
5060 ipv4_addr_show(f, a->encap.vxlan.ipv4.da);
5061 fprintf(f, " %u %u ",
5062 (uint32_t)a->encap.vxlan.ipv4.dscp,
5063 (uint32_t)a->encap.vxlan.ipv4.ttl);
5064 } else {
5065 fprintf(f, " ipv6 ");
5066 ipv6_addr_show(f, a->encap.vxlan.ipv6.sa);
5067 fprintf(f, " ");
5068 ipv6_addr_show(f, a->encap.vxlan.ipv6.da);
5069 fprintf(f, " %u %u %u ",
5070 a->encap.vxlan.ipv6.flow_label,
5071 (uint32_t)a->encap.vxlan.ipv6.dscp,
5072 (uint32_t)a->encap.vxlan.ipv6.hop_limit);
5073 fprintf(f, " udp %u %u vxlan %u ",
5074 a->encap.vxlan.udp.sp,
5075 a->encap.vxlan.udp.dp,
5076 a->encap.vxlan.vxlan.vni);
5077 }
5078 break;
5079
5080 default:
5081 fprintf(f, "unknown ");
5082 }
5083 }
5084
5085 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) {
5086 fprintf(f, "nat %s ", (a->nat.ip_version) ? "ipv4 " : "ipv6 ");
5087 if (a->nat.ip_version)
5088 ipv4_addr_show(f, a->nat.addr.ipv4);
5089 else
5090 ipv6_addr_show(f, a->nat.addr.ipv6);
5091 fprintf(f, " %u ", (uint32_t)(a->nat.port));
5092 }
5093
5094 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TTL))
5095 fprintf(f, "ttl %s ", (a->ttl.decrement) ? "dec" : "keep");
5096
5097 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_STATS))
5098 fprintf(f, "stats ");
5099
5100 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TIME))
5101 fprintf(f, "time ");
5102
5103 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO))
5104 fprintf(f, "sym_crypto ");
5105
5106 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_TAG))
5107 fprintf(f, "tag %u ", a->tag.tag);
5108
5109 if (a->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP))
5110 fprintf(f, "decap %u ", a->decap.n);
5111
5112 /* end */
5113 fprintf(f, "\n");
5114 }
5115
5116 /* Write table default rule to file. */
5117 if (table->rule_default) {
5118 struct table_rule_action *a = &table->rule_default->action;
5119
5120 fprintf(f, "# match default action fwd ");
5121
5122 switch (a->fwd.action) {
5123 case RTE_PIPELINE_ACTION_DROP:
5124 fprintf(f, "drop ");
5125 break;
5126
5127 case RTE_PIPELINE_ACTION_PORT:
5128 fprintf(f, "port %u ", a->fwd.id);
5129 break;
5130
5131 case RTE_PIPELINE_ACTION_PORT_META:
5132 fprintf(f, "meta ");
5133 break;
5134
5135 case RTE_PIPELINE_ACTION_TABLE:
5136 default:
5137 fprintf(f, "table %u ", a->fwd.id);
5138 }
5139 } else
5140 fprintf(f, "# match default action fwd drop ");
5141
5142 fprintf(f, "\n");
5143
5144 /* Close file. */
5145 fclose(f);
5146
5147 return 0;
5148 }
5149
5150 static const char cmd_pipeline_table_rule_show_help[] =
5151 "pipeline <pipeline_name> table <table_id> rule show\n"
5152 " file <file_name>\n";
5153
5154 static void
5155 cmd_pipeline_table_rule_show(char **tokens,
5156 uint32_t n_tokens,
5157 char *out,
5158 size_t out_size)
5159 {
5160 char *file_name = NULL, *pipeline_name;
5161 uint32_t table_id;
5162 int status;
5163
5164 if (n_tokens != 8) {
5165 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5166 return;
5167 }
5168
5169 pipeline_name = tokens[1];
5170
5171 if (strcmp(tokens[2], "table") != 0) {
5172 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
5173 return;
5174 }
5175
5176 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5177 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5178 return;
5179 }
5180
5181 if (strcmp(tokens[4], "rule") != 0) {
5182 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
5183 return;
5184 }
5185
5186 if (strcmp(tokens[5], "show") != 0) {
5187 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "show");
5188 return;
5189 }
5190
5191 if (strcmp(tokens[6], "file") != 0) {
5192 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "file");
5193 return;
5194 }
5195
5196 file_name = tokens[7];
5197
5198 status = table_rule_show(pipeline_name, table_id, file_name);
5199 if (status) {
5200 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5201 return;
5202 }
5203 }
5204
5205 static const char cmd_pipeline_table_rule_stats_read_help[] =
5206 "pipeline <pipeline_name> table <table_id> rule read stats [clear]\n"
5207 " match <match>\n";
5208
5209 static void
5210 cmd_pipeline_table_rule_stats_read(char **tokens,
5211 uint32_t n_tokens,
5212 char *out,
5213 size_t out_size)
5214 {
5215 struct table_rule_match m;
5216 struct rte_table_action_stats_counters stats;
5217 char *pipeline_name;
5218 uint32_t table_id, n_tokens_parsed;
5219 int clear = 0, status;
5220
5221 if (n_tokens < 7) {
5222 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5223 return;
5224 }
5225
5226 pipeline_name = tokens[1];
5227
5228 if (strcmp(tokens[2], "table") != 0) {
5229 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
5230 return;
5231 }
5232
5233 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5234 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5235 return;
5236 }
5237
5238 if (strcmp(tokens[4], "rule") != 0) {
5239 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
5240 return;
5241 }
5242
5243 if (strcmp(tokens[5], "read") != 0) {
5244 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
5245 return;
5246 }
5247
5248 if (strcmp(tokens[6], "stats") != 0) {
5249 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
5250 return;
5251 }
5252
5253 n_tokens -= 7;
5254 tokens += 7;
5255
5256 /* clear */
5257 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) {
5258 clear = 1;
5259
5260 n_tokens--;
5261 tokens++;
5262 }
5263
5264 /* match */
5265 if ((n_tokens == 0) || strcmp(tokens[0], "match")) {
5266 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
5267 return;
5268 }
5269
5270 n_tokens_parsed = parse_match(tokens,
5271 n_tokens,
5272 out,
5273 out_size,
5274 &m);
5275 if (n_tokens_parsed == 0)
5276 return;
5277 n_tokens -= n_tokens_parsed;
5278 tokens += n_tokens_parsed;
5279
5280 /* end */
5281 if (n_tokens) {
5282 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
5283 return;
5284 }
5285
5286 /* Read table rule stats. */
5287 status = pipeline_table_rule_stats_read(pipeline_name,
5288 table_id,
5289 &m,
5290 &stats,
5291 clear);
5292 if (status) {
5293 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5294 return;
5295 }
5296
5297 /* Print stats. */
5298 if (stats.n_packets_valid && stats.n_bytes_valid)
5299 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: %" PRIu64 "\n",
5300 stats.n_packets,
5301 stats.n_bytes);
5302
5303 if (stats.n_packets_valid && !stats.n_bytes_valid)
5304 snprintf(out, out_size, "Packets: %" PRIu64 "; Bytes: N/A\n",
5305 stats.n_packets);
5306
5307 if (!stats.n_packets_valid && stats.n_bytes_valid)
5308 snprintf(out, out_size, "Packets: N/A; Bytes: %" PRIu64 "\n",
5309 stats.n_bytes);
5310
5311 if (!stats.n_packets_valid && !stats.n_bytes_valid)
5312 snprintf(out, out_size, "Packets: N/A ; Bytes: N/A\n");
5313 }
5314
5315 static const char cmd_pipeline_table_meter_profile_add_help[] =
5316 "pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n"
5317 " add srtcm cir <cir> cbs <cbs> ebs <ebs>\n"
5318 " | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n";
5319
5320 static void
5321 cmd_pipeline_table_meter_profile_add(char **tokens,
5322 uint32_t n_tokens,
5323 char *out,
5324 size_t out_size)
5325 {
5326 struct rte_table_action_meter_profile p;
5327 char *pipeline_name;
5328 uint32_t table_id, meter_profile_id;
5329 int status;
5330
5331 if (n_tokens < 9) {
5332 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5333 return;
5334 }
5335
5336 pipeline_name = tokens[1];
5337
5338 if (strcmp(tokens[2], "table") != 0) {
5339 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
5340 return;
5341 }
5342
5343 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5344 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5345 return;
5346 }
5347
5348 if (strcmp(tokens[4], "meter") != 0) {
5349 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
5350 return;
5351 }
5352
5353 if (strcmp(tokens[5], "profile") != 0) {
5354 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
5355 return;
5356 }
5357
5358 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
5359 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
5360 return;
5361 }
5362
5363 if (strcmp(tokens[7], "add") != 0) {
5364 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
5365 return;
5366 }
5367
5368 if (strcmp(tokens[8], "srtcm") == 0) {
5369 if (n_tokens != 15) {
5370 snprintf(out, out_size, MSG_ARG_MISMATCH,
5371 tokens[0]);
5372 return;
5373 }
5374
5375 p.alg = RTE_TABLE_ACTION_METER_SRTCM;
5376
5377 if (strcmp(tokens[9], "cir") != 0) {
5378 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
5379 return;
5380 }
5381
5382 if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
5383 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
5384 return;
5385 }
5386
5387 if (strcmp(tokens[11], "cbs") != 0) {
5388 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
5389 return;
5390 }
5391
5392 if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
5393 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
5394 return;
5395 }
5396
5397 if (strcmp(tokens[13], "ebs") != 0) {
5398 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
5399 return;
5400 }
5401
5402 if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
5403 snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
5404 return;
5405 }
5406 } else if (strcmp(tokens[8], "trtcm") == 0) {
5407 if (n_tokens != 17) {
5408 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5409 return;
5410 }
5411
5412 p.alg = RTE_TABLE_ACTION_METER_TRTCM;
5413
5414 if (strcmp(tokens[9], "cir") != 0) {
5415 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
5416 return;
5417 }
5418
5419 if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
5420 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
5421 return;
5422 }
5423
5424 if (strcmp(tokens[11], "pir") != 0) {
5425 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
5426 return;
5427 }
5428
5429 if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
5430 snprintf(out, out_size, MSG_ARG_INVALID, "pir");
5431 return;
5432 }
5433 if (strcmp(tokens[13], "cbs") != 0) {
5434 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
5435 return;
5436 }
5437
5438 if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
5439 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
5440 return;
5441 }
5442
5443 if (strcmp(tokens[15], "pbs") != 0) {
5444 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
5445 return;
5446 }
5447
5448 if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
5449 snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
5450 return;
5451 }
5452 } else {
5453 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5454 return;
5455 }
5456
5457 status = pipeline_table_mtr_profile_add(pipeline_name,
5458 table_id,
5459 meter_profile_id,
5460 &p);
5461 if (status) {
5462 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5463 return;
5464 }
5465 }
5466
5467
5468 static const char cmd_pipeline_table_meter_profile_delete_help[] =
5469 "pipeline <pipeline_name> table <table_id>\n"
5470 " meter profile <meter_profile_id> delete\n";
5471
5472 static void
5473 cmd_pipeline_table_meter_profile_delete(char **tokens,
5474 uint32_t n_tokens,
5475 char *out,
5476 size_t out_size)
5477 {
5478 char *pipeline_name;
5479 uint32_t table_id, meter_profile_id;
5480 int status;
5481
5482 if (n_tokens != 8) {
5483 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5484 return;
5485 }
5486
5487 pipeline_name = tokens[1];
5488
5489 if (strcmp(tokens[2], "table") != 0) {
5490 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
5491 return;
5492 }
5493
5494 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5495 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5496 return;
5497 }
5498
5499 if (strcmp(tokens[4], "meter") != 0) {
5500 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
5501 return;
5502 }
5503
5504 if (strcmp(tokens[5], "profile") != 0) {
5505 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
5506 return;
5507 }
5508
5509 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
5510 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
5511 return;
5512 }
5513
5514 if (strcmp(tokens[7], "delete") != 0) {
5515 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
5516 return;
5517 }
5518
5519 status = pipeline_table_mtr_profile_delete(pipeline_name,
5520 table_id,
5521 meter_profile_id);
5522 if (status) {
5523 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5524 return;
5525 }
5526 }
5527
5528
5529 static const char cmd_pipeline_table_rule_meter_read_help[] =
5530 "pipeline <pipeline_name> table <table_id> rule read meter [clear]\n"
5531 " match <match>\n";
5532
5533 static void
5534 cmd_pipeline_table_rule_meter_read(char **tokens,
5535 uint32_t n_tokens,
5536 char *out,
5537 size_t out_size)
5538 {
5539 struct table_rule_match m;
5540 struct rte_table_action_mtr_counters stats;
5541 char *pipeline_name;
5542 uint32_t table_id, n_tokens_parsed;
5543 int clear = 0, status;
5544
5545 if (n_tokens < 7) {
5546 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5547 return;
5548 }
5549
5550 pipeline_name = tokens[1];
5551
5552 if (strcmp(tokens[2], "table") != 0) {
5553 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
5554 return;
5555 }
5556
5557 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5558 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5559 return;
5560 }
5561
5562 if (strcmp(tokens[4], "rule") != 0) {
5563 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
5564 return;
5565 }
5566
5567 if (strcmp(tokens[5], "read") != 0) {
5568 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
5569 return;
5570 }
5571
5572 if (strcmp(tokens[6], "meter") != 0) {
5573 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
5574 return;
5575 }
5576
5577 n_tokens -= 7;
5578 tokens += 7;
5579
5580 /* clear */
5581 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) {
5582 clear = 1;
5583
5584 n_tokens--;
5585 tokens++;
5586 }
5587
5588 /* match */
5589 if ((n_tokens == 0) || strcmp(tokens[0], "match")) {
5590 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
5591 return;
5592 }
5593
5594 n_tokens_parsed = parse_match(tokens,
5595 n_tokens,
5596 out,
5597 out_size,
5598 &m);
5599 if (n_tokens_parsed == 0)
5600 return;
5601 n_tokens -= n_tokens_parsed;
5602 tokens += n_tokens_parsed;
5603
5604 /* end */
5605 if (n_tokens) {
5606 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
5607 return;
5608 }
5609
5610 /* Read table rule meter stats. */
5611 status = pipeline_table_rule_mtr_read(pipeline_name,
5612 table_id,
5613 &m,
5614 &stats,
5615 clear);
5616 if (status) {
5617 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5618 return;
5619 }
5620
5621 /* Print stats. */
5622 }
5623
5624
5625 static const char cmd_pipeline_table_dscp_help[] =
5626 "pipeline <pipeline_name> table <table_id> dscp <file_name>\n"
5627 "\n"
5628 " File <file_name>:\n"
5629 " - exactly 64 lines\n"
5630 " - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n";
5631
5632 static int
5633 load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
5634 const char *file_name,
5635 uint32_t *line_number)
5636 {
5637 FILE *f = NULL;
5638 uint32_t dscp, l;
5639
5640 /* Check input arguments */
5641 if ((dscp_table == NULL) ||
5642 (file_name == NULL) ||
5643 (line_number == NULL)) {
5644 if (line_number)
5645 *line_number = 0;
5646 return -EINVAL;
5647 }
5648
5649 /* Open input file */
5650 f = fopen(file_name, "r");
5651 if (f == NULL) {
5652 *line_number = 0;
5653 return -EINVAL;
5654 }
5655
5656 /* Read file */
5657 for (dscp = 0, l = 1; ; l++) {
5658 char line[64];
5659 char *tokens[3];
5660 enum rte_color color;
5661 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
5662
5663 if (fgets(line, sizeof(line), f) == NULL)
5664 break;
5665
5666 if (is_comment(line))
5667 continue;
5668
5669 if (parse_tokenize_string(line, tokens, &n_tokens)) {
5670 *line_number = l;
5671 fclose(f);
5672 return -EINVAL;
5673 }
5674
5675 if (n_tokens == 0)
5676 continue;
5677
5678 if ((dscp >= RTE_DIM(dscp_table->entry)) ||
5679 (n_tokens != RTE_DIM(tokens)) ||
5680 parser_read_uint32(&tc_id, tokens[0]) ||
5681 (tc_id >= RTE_TABLE_ACTION_TC_MAX) ||
5682 parser_read_uint32(&tc_queue_id, tokens[1]) ||
5683 (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) ||
5684 (strlen(tokens[2]) != 1)) {
5685 *line_number = l;
5686 fclose(f);
5687 return -EINVAL;
5688 }
5689
5690 switch (tokens[2][0]) {
5691 case 'g':
5692 case 'G':
5693 color = RTE_COLOR_GREEN;
5694 break;
5695
5696 case 'y':
5697 case 'Y':
5698 color = RTE_COLOR_YELLOW;
5699 break;
5700
5701 case 'r':
5702 case 'R':
5703 color = RTE_COLOR_RED;
5704 break;
5705
5706 default:
5707 *line_number = l;
5708 fclose(f);
5709 return -EINVAL;
5710 }
5711
5712 dscp_table->entry[dscp].tc_id = tc_id;
5713 dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
5714 dscp_table->entry[dscp].color = color;
5715 dscp++;
5716 }
5717
5718 /* Close file */
5719 fclose(f);
5720 return 0;
5721 }
5722
5723 static void
5724 cmd_pipeline_table_dscp(char **tokens,
5725 uint32_t n_tokens,
5726 char *out,
5727 size_t out_size)
5728 {
5729 struct rte_table_action_dscp_table dscp_table;
5730 char *pipeline_name, *file_name;
5731 uint32_t table_id, line_number;
5732 int status;
5733
5734 if (n_tokens != 6) {
5735 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5736 return;
5737 }
5738
5739 pipeline_name = tokens[1];
5740
5741 if (strcmp(tokens[2], "table") != 0) {
5742 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
5743 return;
5744 }
5745
5746 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5747 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5748 return;
5749 }
5750
5751 if (strcmp(tokens[4], "dscp") != 0) {
5752 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
5753 return;
5754 }
5755
5756 file_name = tokens[5];
5757
5758 status = load_dscp_table(&dscp_table, file_name, &line_number);
5759 if (status) {
5760 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
5761 return;
5762 }
5763
5764 status = pipeline_table_dscp_table_update(pipeline_name,
5765 table_id,
5766 UINT64_MAX,
5767 &dscp_table);
5768 if (status) {
5769 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5770 return;
5771 }
5772 }
5773
5774
5775 static const char cmd_pipeline_table_rule_ttl_read_help[] =
5776 "pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n"
5777 " match <match>\n";
5778
5779 static void
5780 cmd_pipeline_table_rule_ttl_read(char **tokens,
5781 uint32_t n_tokens,
5782 char *out,
5783 size_t out_size)
5784 {
5785 struct table_rule_match m;
5786 struct rte_table_action_ttl_counters stats;
5787 char *pipeline_name;
5788 uint32_t table_id, n_tokens_parsed;
5789 int clear = 0, status;
5790
5791 if (n_tokens < 7) {
5792 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5793 return;
5794 }
5795
5796 pipeline_name = tokens[1];
5797
5798 if (strcmp(tokens[2], "table") != 0) {
5799 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
5800 return;
5801 }
5802
5803 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5804 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5805 return;
5806 }
5807
5808 if (strcmp(tokens[4], "rule") != 0) {
5809 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
5810 return;
5811 }
5812
5813 if (strcmp(tokens[5], "read") != 0) {
5814 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
5815 return;
5816 }
5817
5818 if (strcmp(tokens[6], "ttl") != 0) {
5819 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ttl");
5820 return;
5821 }
5822
5823 n_tokens -= 7;
5824 tokens += 7;
5825
5826 /* clear */
5827 if (n_tokens && (strcmp(tokens[0], "clear") == 0)) {
5828 clear = 1;
5829
5830 n_tokens--;
5831 tokens++;
5832 }
5833
5834 /* match */
5835 if ((n_tokens == 0) || strcmp(tokens[0], "match")) {
5836 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
5837 return;
5838 }
5839
5840 n_tokens_parsed = parse_match(tokens,
5841 n_tokens,
5842 out,
5843 out_size,
5844 &m);
5845 if (n_tokens_parsed == 0)
5846 return;
5847 n_tokens -= n_tokens_parsed;
5848 tokens += n_tokens_parsed;
5849
5850 /* end */
5851 if (n_tokens) {
5852 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
5853 return;
5854 }
5855
5856 /* Read table rule TTL stats. */
5857 status = pipeline_table_rule_ttl_read(pipeline_name,
5858 table_id,
5859 &m,
5860 &stats,
5861 clear);
5862 if (status) {
5863 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5864 return;
5865 }
5866
5867 /* Print stats. */
5868 snprintf(out, out_size, "Packets: %" PRIu64 "\n",
5869 stats.n_packets);
5870 }
5871
5872 static const char cmd_pipeline_table_rule_time_read_help[] =
5873 "pipeline <pipeline_name> table <table_id> rule read time\n"
5874 " match <match>\n";
5875
5876 static void
5877 cmd_pipeline_table_rule_time_read(char **tokens,
5878 uint32_t n_tokens,
5879 char *out,
5880 size_t out_size)
5881 {
5882 struct table_rule_match m;
5883 char *pipeline_name;
5884 uint64_t timestamp;
5885 uint32_t table_id, n_tokens_parsed;
5886 int status;
5887
5888 if (n_tokens < 7) {
5889 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5890 return;
5891 }
5892
5893 pipeline_name = tokens[1];
5894
5895 if (strcmp(tokens[2], "table") != 0) {
5896 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
5897 return;
5898 }
5899
5900 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
5901 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
5902 return;
5903 }
5904
5905 if (strcmp(tokens[4], "rule") != 0) {
5906 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
5907 return;
5908 }
5909
5910 if (strcmp(tokens[5], "read") != 0) {
5911 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
5912 return;
5913 }
5914
5915 if (strcmp(tokens[6], "time") != 0) {
5916 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "time");
5917 return;
5918 }
5919
5920 n_tokens -= 7;
5921 tokens += 7;
5922
5923 /* match */
5924 if ((n_tokens == 0) || strcmp(tokens[0], "match")) {
5925 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
5926 return;
5927 }
5928
5929 n_tokens_parsed = parse_match(tokens,
5930 n_tokens,
5931 out,
5932 out_size,
5933 &m);
5934 if (n_tokens_parsed == 0)
5935 return;
5936 n_tokens -= n_tokens_parsed;
5937 tokens += n_tokens_parsed;
5938
5939 /* end */
5940 if (n_tokens) {
5941 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
5942 return;
5943 }
5944
5945 /* Read table rule timestamp. */
5946 status = pipeline_table_rule_time_read(pipeline_name,
5947 table_id,
5948 &m,
5949 &timestamp);
5950 if (status) {
5951 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
5952 return;
5953 }
5954
5955 /* Print stats. */
5956 snprintf(out, out_size, "Packets: %" PRIu64 "\n", timestamp);
5957 }
5958
5959 static const char cmd_thread_pipeline_enable_help[] =
5960 "thread <thread_id> pipeline <pipeline_name> enable\n";
5961
5962 static void
5963 cmd_thread_pipeline_enable(char **tokens,
5964 uint32_t n_tokens,
5965 char *out,
5966 size_t out_size)
5967 {
5968 char *pipeline_name;
5969 uint32_t thread_id;
5970 int status;
5971
5972 if (n_tokens != 5) {
5973 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
5974 return;
5975 }
5976
5977 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
5978 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
5979 return;
5980 }
5981
5982 if (strcmp(tokens[2], "pipeline") != 0) {
5983 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
5984 return;
5985 }
5986
5987 pipeline_name = tokens[3];
5988
5989 if (strcmp(tokens[4], "enable") != 0) {
5990 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
5991 return;
5992 }
5993
5994 status = thread_pipeline_enable(thread_id, pipeline_name);
5995 if (status) {
5996 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
5997 return;
5998 }
5999 }
6000
6001
6002 static const char cmd_thread_pipeline_disable_help[] =
6003 "thread <thread_id> pipeline <pipeline_name> disable\n";
6004
6005 static void
6006 cmd_thread_pipeline_disable(char **tokens,
6007 uint32_t n_tokens,
6008 char *out,
6009 size_t out_size)
6010 {
6011 char *pipeline_name;
6012 uint32_t thread_id;
6013 int status;
6014
6015 if (n_tokens != 5) {
6016 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
6017 return;
6018 }
6019
6020 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
6021 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
6022 return;
6023 }
6024
6025 if (strcmp(tokens[2], "pipeline") != 0) {
6026 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
6027 return;
6028 }
6029
6030 pipeline_name = tokens[3];
6031
6032 if (strcmp(tokens[4], "disable") != 0) {
6033 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
6034 return;
6035 }
6036
6037 status = thread_pipeline_disable(thread_id, pipeline_name);
6038 if (status) {
6039 snprintf(out, out_size, MSG_CMD_FAIL,
6040 "thread pipeline disable");
6041 return;
6042 }
6043 }
6044
6045 static void
6046 cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size)
6047 {
6048 tokens++;
6049 n_tokens--;
6050
6051 if (n_tokens == 0) {
6052 snprintf(out, out_size,
6053 "Type 'help <command>' for details on each command.\n\n"
6054 "List of commands:\n"
6055 "\tmempool\n"
6056 "\tlink\n"
6057 "\tswq\n"
6058 "\ttmgr subport profile\n"
6059 "\ttmgr pipe profile\n"
6060 "\ttmgr\n"
6061 "\ttmgr subport\n"
6062 "\ttmgr subport pipe\n"
6063 "\ttap\n"
6064 "\tkni\n"
6065 "\tport in action profile\n"
6066 "\ttable action profile\n"
6067 "\tpipeline\n"
6068 "\tpipeline port in\n"
6069 "\tpipeline port out\n"
6070 "\tpipeline table\n"
6071 "\tpipeline port in table\n"
6072 "\tpipeline port in stats\n"
6073 "\tpipeline port in enable\n"
6074 "\tpipeline port in disable\n"
6075 "\tpipeline port out stats\n"
6076 "\tpipeline table stats\n"
6077 "\tpipeline table rule add\n"
6078 "\tpipeline table rule add default\n"
6079 "\tpipeline table rule add bulk\n"
6080 "\tpipeline table rule delete\n"
6081 "\tpipeline table rule delete default\n"
6082 "\tpipeline table rule show\n"
6083 "\tpipeline table rule stats read\n"
6084 "\tpipeline table meter profile add\n"
6085 "\tpipeline table meter profile delete\n"
6086 "\tpipeline table rule meter read\n"
6087 "\tpipeline table dscp\n"
6088 "\tpipeline table rule ttl read\n"
6089 "\tpipeline table rule time read\n"
6090 "\tthread pipeline enable\n"
6091 "\tthread pipeline disable\n\n");
6092 return;
6093 }
6094
6095 if (strcmp(tokens[0], "mempool") == 0) {
6096 snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
6097 return;
6098 }
6099
6100 if (strcmp(tokens[0], "link") == 0) {
6101 snprintf(out, out_size, "\n%s\n", cmd_link_help);
6102 return;
6103 }
6104
6105 if (strcmp(tokens[0], "swq") == 0) {
6106 snprintf(out, out_size, "\n%s\n", cmd_swq_help);
6107 return;
6108 }
6109
6110 if (strcmp(tokens[0], "tmgr") == 0) {
6111 if (n_tokens == 1) {
6112 snprintf(out, out_size, "\n%s\n", cmd_tmgr_help);
6113 return;
6114 }
6115
6116 if ((n_tokens == 2) &&
6117 (strcmp(tokens[1], "subport")) == 0) {
6118 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help);
6119 return;
6120 }
6121
6122 if ((n_tokens == 3) &&
6123 (strcmp(tokens[1], "subport") == 0) &&
6124 (strcmp(tokens[2], "profile") == 0)) {
6125 snprintf(out, out_size, "\n%s\n",
6126 cmd_tmgr_subport_profile_help);
6127 return;
6128 }
6129
6130 if ((n_tokens == 3) &&
6131 (strcmp(tokens[1], "subport") == 0) &&
6132 (strcmp(tokens[2], "pipe") == 0)) {
6133 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help);
6134 return;
6135 }
6136
6137 if ((n_tokens == 3) &&
6138 (strcmp(tokens[1], "pipe") == 0) &&
6139 (strcmp(tokens[2], "profile") == 0)) {
6140 snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help);
6141 return;
6142 }
6143 }
6144
6145 if (strcmp(tokens[0], "tap") == 0) {
6146 snprintf(out, out_size, "\n%s\n", cmd_tap_help);
6147 return;
6148 }
6149
6150 if (strcmp(tokens[0], "kni") == 0) {
6151 snprintf(out, out_size, "\n%s\n", cmd_kni_help);
6152 return;
6153 }
6154
6155 if (strcmp(tokens[0], "cryptodev") == 0) {
6156 snprintf(out, out_size, "\n%s\n", cmd_cryptodev_help);
6157 return;
6158 }
6159
6160 if ((n_tokens == 4) &&
6161 (strcmp(tokens[0], "port") == 0) &&
6162 (strcmp(tokens[1], "in") == 0) &&
6163 (strcmp(tokens[2], "action") == 0) &&
6164 (strcmp(tokens[3], "profile") == 0)) {
6165 snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help);
6166 return;
6167 }
6168
6169 if ((n_tokens == 3) &&
6170 (strcmp(tokens[0], "table") == 0) &&
6171 (strcmp(tokens[1], "action") == 0) &&
6172 (strcmp(tokens[2], "profile") == 0)) {
6173 snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help);
6174 return;
6175 }
6176
6177 if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) {
6178 snprintf(out, out_size, "\n%s\n", cmd_pipeline_help);
6179 return;
6180 }
6181
6182 if ((strcmp(tokens[0], "pipeline") == 0) &&
6183 (strcmp(tokens[1], "port") == 0)) {
6184 if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) {
6185 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help);
6186 return;
6187 }
6188
6189 if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) {
6190 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help);
6191 return;
6192 }
6193
6194 if ((n_tokens == 4) &&
6195 (strcmp(tokens[2], "in") == 0) &&
6196 (strcmp(tokens[3], "table") == 0)) {
6197 snprintf(out, out_size, "\n%s\n",
6198 cmd_pipeline_port_in_table_help);
6199 return;
6200 }
6201
6202 if ((n_tokens == 4) &&
6203 (strcmp(tokens[2], "in") == 0) &&
6204 (strcmp(tokens[3], "stats") == 0)) {
6205 snprintf(out, out_size, "\n%s\n",
6206 cmd_pipeline_port_in_stats_help);
6207 return;
6208 }
6209
6210 if ((n_tokens == 4) &&
6211 (strcmp(tokens[2], "in") == 0) &&
6212 (strcmp(tokens[3], "enable") == 0)) {
6213 snprintf(out, out_size, "\n%s\n",
6214 cmd_pipeline_port_in_enable_help);
6215 return;
6216 }
6217
6218 if ((n_tokens == 4) &&
6219 (strcmp(tokens[2], "in") == 0) &&
6220 (strcmp(tokens[3], "disable") == 0)) {
6221 snprintf(out, out_size, "\n%s\n",
6222 cmd_pipeline_port_in_disable_help);
6223 return;
6224 }
6225
6226 if ((n_tokens == 4) &&
6227 (strcmp(tokens[2], "out") == 0) &&
6228 (strcmp(tokens[3], "stats") == 0)) {
6229 snprintf(out, out_size, "\n%s\n",
6230 cmd_pipeline_port_out_stats_help);
6231 return;
6232 }
6233 }
6234
6235 if ((strcmp(tokens[0], "pipeline") == 0) &&
6236 (strcmp(tokens[1], "table") == 0)) {
6237 if (n_tokens == 2) {
6238 snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help);
6239 return;
6240 }
6241
6242 if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) {
6243 snprintf(out, out_size, "\n%s\n",
6244 cmd_pipeline_table_stats_help);
6245 return;
6246 }
6247
6248 if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) {
6249 snprintf(out, out_size, "\n%s\n",
6250 cmd_pipeline_table_dscp_help);
6251 return;
6252 }
6253
6254 if ((n_tokens == 4) &&
6255 (strcmp(tokens[2], "rule") == 0) &&
6256 (strcmp(tokens[3], "add") == 0)) {
6257 snprintf(out, out_size, "\n%s\n",
6258 cmd_pipeline_table_rule_add_help);
6259 return;
6260 }
6261
6262 if ((n_tokens == 5) &&
6263 (strcmp(tokens[2], "rule") == 0) &&
6264 (strcmp(tokens[3], "add") == 0) &&
6265 (strcmp(tokens[4], "default") == 0)) {
6266 snprintf(out, out_size, "\n%s\n",
6267 cmd_pipeline_table_rule_add_default_help);
6268 return;
6269 }
6270
6271 if ((n_tokens == 5) &&
6272 (strcmp(tokens[2], "rule") == 0) &&
6273 (strcmp(tokens[3], "add") == 0) &&
6274 (strcmp(tokens[4], "bulk") == 0)) {
6275 snprintf(out, out_size, "\n%s\n",
6276 cmd_pipeline_table_rule_add_bulk_help);
6277 return;
6278 }
6279
6280 if ((n_tokens == 4) &&
6281 (strcmp(tokens[2], "rule") == 0) &&
6282 (strcmp(tokens[3], "delete") == 0)) {
6283 snprintf(out, out_size, "\n%s\n",
6284 cmd_pipeline_table_rule_delete_help);
6285 return;
6286 }
6287
6288 if ((n_tokens == 5) &&
6289 (strcmp(tokens[2], "rule") == 0) &&
6290 (strcmp(tokens[3], "delete") == 0) &&
6291 (strcmp(tokens[4], "default") == 0)) {
6292 snprintf(out, out_size, "\n%s\n",
6293 cmd_pipeline_table_rule_delete_default_help);
6294 return;
6295 }
6296
6297 if ((n_tokens == 4) &&
6298 (strcmp(tokens[2], "rule") == 0) &&
6299 (strcmp(tokens[3], "show") == 0)) {
6300 snprintf(out, out_size, "\n%s\n",
6301 cmd_pipeline_table_rule_show_help);
6302 return;
6303 }
6304
6305 if ((n_tokens == 5) &&
6306 (strcmp(tokens[2], "rule") == 0) &&
6307 (strcmp(tokens[3], "stats") == 0) &&
6308 (strcmp(tokens[4], "read") == 0)) {
6309 snprintf(out, out_size, "\n%s\n",
6310 cmd_pipeline_table_rule_stats_read_help);
6311 return;
6312 }
6313
6314 if ((n_tokens == 5) &&
6315 (strcmp(tokens[2], "meter") == 0) &&
6316 (strcmp(tokens[3], "profile") == 0) &&
6317 (strcmp(tokens[4], "add") == 0)) {
6318 snprintf(out, out_size, "\n%s\n",
6319 cmd_pipeline_table_meter_profile_add_help);
6320 return;
6321 }
6322
6323 if ((n_tokens == 5) &&
6324 (strcmp(tokens[2], "meter") == 0) &&
6325 (strcmp(tokens[3], "profile") == 0) &&
6326 (strcmp(tokens[4], "delete") == 0)) {
6327 snprintf(out, out_size, "\n%s\n",
6328 cmd_pipeline_table_meter_profile_delete_help);
6329 return;
6330 }
6331
6332 if ((n_tokens == 5) &&
6333 (strcmp(tokens[2], "rule") == 0) &&
6334 (strcmp(tokens[3], "meter") == 0) &&
6335 (strcmp(tokens[4], "read") == 0)) {
6336 snprintf(out, out_size, "\n%s\n",
6337 cmd_pipeline_table_rule_meter_read_help);
6338 return;
6339 }
6340
6341 if ((n_tokens == 5) &&
6342 (strcmp(tokens[2], "rule") == 0) &&
6343 (strcmp(tokens[3], "ttl") == 0) &&
6344 (strcmp(tokens[4], "read") == 0)) {
6345 snprintf(out, out_size, "\n%s\n",
6346 cmd_pipeline_table_rule_ttl_read_help);
6347 return;
6348 }
6349
6350 if ((n_tokens == 5) &&
6351 (strcmp(tokens[2], "rule") == 0) &&
6352 (strcmp(tokens[3], "time") == 0) &&
6353 (strcmp(tokens[4], "read") == 0)) {
6354 snprintf(out, out_size, "\n%s\n",
6355 cmd_pipeline_table_rule_time_read_help);
6356 return;
6357 }
6358 }
6359
6360 if ((n_tokens == 3) &&
6361 (strcmp(tokens[0], "thread") == 0) &&
6362 (strcmp(tokens[1], "pipeline") == 0)) {
6363 if (strcmp(tokens[2], "enable") == 0) {
6364 snprintf(out, out_size, "\n%s\n",
6365 cmd_thread_pipeline_enable_help);
6366 return;
6367 }
6368
6369 if (strcmp(tokens[2], "disable") == 0) {
6370 snprintf(out, out_size, "\n%s\n",
6371 cmd_thread_pipeline_disable_help);
6372 return;
6373 }
6374 }
6375
6376 snprintf(out, out_size, "Invalid command\n");
6377 }
6378
6379 void
6380 cli_process(char *in, char *out, size_t out_size)
6381 {
6382 char *tokens[CMD_MAX_TOKENS];
6383 uint32_t n_tokens = RTE_DIM(tokens);
6384 int status;
6385
6386 if (is_comment(in))
6387 return;
6388
6389 status = parse_tokenize_string(in, tokens, &n_tokens);
6390 if (status) {
6391 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
6392 return;
6393 }
6394
6395 if (n_tokens == 0)
6396 return;
6397
6398 if (strcmp(tokens[0], "help") == 0) {
6399 cmd_help(tokens, n_tokens, out, out_size);
6400 return;
6401 }
6402
6403 if (strcmp(tokens[0], "mempool") == 0) {
6404 cmd_mempool(tokens, n_tokens, out, out_size);
6405 return;
6406 }
6407
6408 if (strcmp(tokens[0], "link") == 0) {
6409 if (strcmp(tokens[1], "show") == 0) {
6410 cmd_link_show(tokens, n_tokens, out, out_size);
6411 return;
6412 }
6413
6414 cmd_link(tokens, n_tokens, out, out_size);
6415 return;
6416 }
6417
6418 if (strcmp(tokens[0], "swq") == 0) {
6419 cmd_swq(tokens, n_tokens, out, out_size);
6420 return;
6421 }
6422
6423 if (strcmp(tokens[0], "tmgr") == 0) {
6424 if ((n_tokens >= 3) &&
6425 (strcmp(tokens[1], "subport") == 0) &&
6426 (strcmp(tokens[2], "profile") == 0)) {
6427 cmd_tmgr_subport_profile(tokens, n_tokens,
6428 out, out_size);
6429 return;
6430 }
6431
6432 if ((n_tokens >= 3) &&
6433 (strcmp(tokens[1], "pipe") == 0) &&
6434 (strcmp(tokens[2], "profile") == 0)) {
6435 cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size);
6436 return;
6437 }
6438
6439 if ((n_tokens >= 5) &&
6440 (strcmp(tokens[2], "subport") == 0) &&
6441 (strcmp(tokens[4], "profile") == 0)) {
6442 cmd_tmgr_subport(tokens, n_tokens, out, out_size);
6443 return;
6444 }
6445
6446 if ((n_tokens >= 5) &&
6447 (strcmp(tokens[2], "subport") == 0) &&
6448 (strcmp(tokens[4], "pipe") == 0)) {
6449 cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size);
6450 return;
6451 }
6452
6453 cmd_tmgr(tokens, n_tokens, out, out_size);
6454 return;
6455 }
6456
6457 if (strcmp(tokens[0], "tap") == 0) {
6458 cmd_tap(tokens, n_tokens, out, out_size);
6459 return;
6460 }
6461
6462 if (strcmp(tokens[0], "kni") == 0) {
6463 cmd_kni(tokens, n_tokens, out, out_size);
6464 return;
6465 }
6466
6467 if (strcmp(tokens[0], "cryptodev") == 0) {
6468 cmd_cryptodev(tokens, n_tokens, out, out_size);
6469 return;
6470 }
6471
6472 if (strcmp(tokens[0], "port") == 0) {
6473 cmd_port_in_action_profile(tokens, n_tokens, out, out_size);
6474 return;
6475 }
6476
6477 if (strcmp(tokens[0], "table") == 0) {
6478 cmd_table_action_profile(tokens, n_tokens, out, out_size);
6479 return;
6480 }
6481
6482 if (strcmp(tokens[0], "pipeline") == 0) {
6483 if ((n_tokens >= 3) &&
6484 (strcmp(tokens[2], "period") == 0)) {
6485 cmd_pipeline(tokens, n_tokens, out, out_size);
6486 return;
6487 }
6488
6489 if ((n_tokens >= 5) &&
6490 (strcmp(tokens[2], "port") == 0) &&
6491 (strcmp(tokens[3], "in") == 0) &&
6492 (strcmp(tokens[4], "bsz") == 0)) {
6493 cmd_pipeline_port_in(tokens, n_tokens, out, out_size);
6494 return;
6495 }
6496
6497 if ((n_tokens >= 5) &&
6498 (strcmp(tokens[2], "port") == 0) &&
6499 (strcmp(tokens[3], "out") == 0) &&
6500 (strcmp(tokens[4], "bsz") == 0)) {
6501 cmd_pipeline_port_out(tokens, n_tokens, out, out_size);
6502 return;
6503 }
6504
6505 if ((n_tokens >= 4) &&
6506 (strcmp(tokens[2], "table") == 0) &&
6507 (strcmp(tokens[3], "match") == 0)) {
6508 cmd_pipeline_table(tokens, n_tokens, out, out_size);
6509 return;
6510 }
6511
6512 if ((n_tokens >= 6) &&
6513 (strcmp(tokens[2], "port") == 0) &&
6514 (strcmp(tokens[3], "in") == 0) &&
6515 (strcmp(tokens[5], "table") == 0)) {
6516 cmd_pipeline_port_in_table(tokens, n_tokens,
6517 out, out_size);
6518 return;
6519 }
6520
6521 if ((n_tokens >= 6) &&
6522 (strcmp(tokens[2], "port") == 0) &&
6523 (strcmp(tokens[3], "in") == 0) &&
6524 (strcmp(tokens[5], "stats") == 0)) {
6525 cmd_pipeline_port_in_stats(tokens, n_tokens,
6526 out, out_size);
6527 return;
6528 }
6529
6530 if ((n_tokens >= 6) &&
6531 (strcmp(tokens[2], "port") == 0) &&
6532 (strcmp(tokens[3], "in") == 0) &&
6533 (strcmp(tokens[5], "enable") == 0)) {
6534 cmd_pipeline_port_in_enable(tokens, n_tokens,
6535 out, out_size);
6536 return;
6537 }
6538
6539 if ((n_tokens >= 6) &&
6540 (strcmp(tokens[2], "port") == 0) &&
6541 (strcmp(tokens[3], "in") == 0) &&
6542 (strcmp(tokens[5], "disable") == 0)) {
6543 cmd_pipeline_port_in_disable(tokens, n_tokens,
6544 out, out_size);
6545 return;
6546 }
6547
6548 if ((n_tokens >= 6) &&
6549 (strcmp(tokens[2], "port") == 0) &&
6550 (strcmp(tokens[3], "out") == 0) &&
6551 (strcmp(tokens[5], "stats") == 0)) {
6552 cmd_pipeline_port_out_stats(tokens, n_tokens,
6553 out, out_size);
6554 return;
6555 }
6556
6557 if ((n_tokens >= 5) &&
6558 (strcmp(tokens[2], "table") == 0) &&
6559 (strcmp(tokens[4], "stats") == 0)) {
6560 cmd_pipeline_table_stats(tokens, n_tokens,
6561 out, out_size);
6562 return;
6563 }
6564
6565 if ((n_tokens >= 7) &&
6566 (strcmp(tokens[2], "table") == 0) &&
6567 (strcmp(tokens[4], "rule") == 0) &&
6568 (strcmp(tokens[5], "add") == 0) &&
6569 (strcmp(tokens[6], "match") == 0)) {
6570 if ((n_tokens >= 8) &&
6571 (strcmp(tokens[7], "default") == 0)) {
6572 cmd_pipeline_table_rule_add_default(tokens,
6573 n_tokens, out, out_size);
6574 return;
6575 }
6576
6577 cmd_pipeline_table_rule_add(tokens, n_tokens,
6578 out, out_size);
6579 return;
6580 }
6581
6582 if ((n_tokens >= 7) &&
6583 (strcmp(tokens[2], "table") == 0) &&
6584 (strcmp(tokens[4], "rule") == 0) &&
6585 (strcmp(tokens[5], "add") == 0) &&
6586 (strcmp(tokens[6], "bulk") == 0)) {
6587 cmd_pipeline_table_rule_add_bulk(tokens,
6588 n_tokens, out, out_size);
6589 return;
6590 }
6591
6592 if ((n_tokens >= 7) &&
6593 (strcmp(tokens[2], "table") == 0) &&
6594 (strcmp(tokens[4], "rule") == 0) &&
6595 (strcmp(tokens[5], "delete") == 0) &&
6596 (strcmp(tokens[6], "match") == 0)) {
6597 if ((n_tokens >= 8) &&
6598 (strcmp(tokens[7], "default") == 0)) {
6599 cmd_pipeline_table_rule_delete_default(tokens,
6600 n_tokens, out, out_size);
6601 return;
6602 }
6603
6604 cmd_pipeline_table_rule_delete(tokens, n_tokens,
6605 out, out_size);
6606 return;
6607 }
6608
6609 if ((n_tokens >= 6) &&
6610 (strcmp(tokens[2], "table") == 0) &&
6611 (strcmp(tokens[4], "rule") == 0) &&
6612 (strcmp(tokens[5], "show") == 0)) {
6613 cmd_pipeline_table_rule_show(tokens, n_tokens,
6614 out, out_size);
6615 return;
6616 }
6617
6618 if ((n_tokens >= 7) &&
6619 (strcmp(tokens[2], "table") == 0) &&
6620 (strcmp(tokens[4], "rule") == 0) &&
6621 (strcmp(tokens[5], "read") == 0) &&
6622 (strcmp(tokens[6], "stats") == 0)) {
6623 cmd_pipeline_table_rule_stats_read(tokens, n_tokens,
6624 out, out_size);
6625 return;
6626 }
6627
6628 if ((n_tokens >= 8) &&
6629 (strcmp(tokens[2], "table") == 0) &&
6630 (strcmp(tokens[4], "meter") == 0) &&
6631 (strcmp(tokens[5], "profile") == 0) &&
6632 (strcmp(tokens[7], "add") == 0)) {
6633 cmd_pipeline_table_meter_profile_add(tokens, n_tokens,
6634 out, out_size);
6635 return;
6636 }
6637
6638 if ((n_tokens >= 8) &&
6639 (strcmp(tokens[2], "table") == 0) &&
6640 (strcmp(tokens[4], "meter") == 0) &&
6641 (strcmp(tokens[5], "profile") == 0) &&
6642 (strcmp(tokens[7], "delete") == 0)) {
6643 cmd_pipeline_table_meter_profile_delete(tokens,
6644 n_tokens, out, out_size);
6645 return;
6646 }
6647
6648 if ((n_tokens >= 7) &&
6649 (strcmp(tokens[2], "table") == 0) &&
6650 (strcmp(tokens[4], "rule") == 0) &&
6651 (strcmp(tokens[5], "read") == 0) &&
6652 (strcmp(tokens[6], "meter") == 0)) {
6653 cmd_pipeline_table_rule_meter_read(tokens, n_tokens,
6654 out, out_size);
6655 return;
6656 }
6657
6658 if ((n_tokens >= 5) &&
6659 (strcmp(tokens[2], "table") == 0) &&
6660 (strcmp(tokens[4], "dscp") == 0)) {
6661 cmd_pipeline_table_dscp(tokens, n_tokens,
6662 out, out_size);
6663 return;
6664 }
6665
6666 if ((n_tokens >= 7) &&
6667 (strcmp(tokens[2], "table") == 0) &&
6668 (strcmp(tokens[4], "rule") == 0) &&
6669 (strcmp(tokens[5], "read") == 0) &&
6670 (strcmp(tokens[6], "ttl") == 0)) {
6671 cmd_pipeline_table_rule_ttl_read(tokens, n_tokens,
6672 out, out_size);
6673 return;
6674 }
6675
6676 if ((n_tokens >= 7) &&
6677 (strcmp(tokens[2], "table") == 0) &&
6678 (strcmp(tokens[4], "rule") == 0) &&
6679 (strcmp(tokens[5], "read") == 0) &&
6680 (strcmp(tokens[6], "time") == 0)) {
6681 cmd_pipeline_table_rule_time_read(tokens, n_tokens,
6682 out, out_size);
6683 return;
6684 }
6685 }
6686
6687 if (strcmp(tokens[0], "thread") == 0) {
6688 if ((n_tokens >= 5) &&
6689 (strcmp(tokens[4], "enable") == 0)) {
6690 cmd_thread_pipeline_enable(tokens, n_tokens,
6691 out, out_size);
6692 return;
6693 }
6694
6695 if ((n_tokens >= 5) &&
6696 (strcmp(tokens[4], "disable") == 0)) {
6697 cmd_thread_pipeline_disable(tokens, n_tokens,
6698 out, out_size);
6699 return;
6700 }
6701 }
6702
6703 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
6704 }
6705
6706 int
6707 cli_script_process(const char *file_name,
6708 size_t msg_in_len_max,
6709 size_t msg_out_len_max)
6710 {
6711 char *msg_in = NULL, *msg_out = NULL;
6712 FILE *f = NULL;
6713
6714 /* Check input arguments */
6715 if ((file_name == NULL) ||
6716 (strlen(file_name) == 0) ||
6717 (msg_in_len_max == 0) ||
6718 (msg_out_len_max == 0))
6719 return -EINVAL;
6720
6721 msg_in = malloc(msg_in_len_max + 1);
6722 msg_out = malloc(msg_out_len_max + 1);
6723 if ((msg_in == NULL) ||
6724 (msg_out == NULL)) {
6725 free(msg_out);
6726 free(msg_in);
6727 return -ENOMEM;
6728 }
6729
6730 /* Open input file */
6731 f = fopen(file_name, "r");
6732 if (f == NULL) {
6733 free(msg_out);
6734 free(msg_in);
6735 return -EIO;
6736 }
6737
6738 /* Read file */
6739 for ( ; ; ) {
6740 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
6741 break;
6742
6743 printf("%s", msg_in);
6744 msg_out[0] = 0;
6745
6746 cli_process(msg_in,
6747 msg_out,
6748 msg_out_len_max);
6749
6750 if (strlen(msg_out))
6751 printf("%s", msg_out);
6752 }
6753
6754 /* Close file */
6755 fclose(f);
6756 free(msg_out);
6757 free(msg_in);
6758 return 0;
6759 }
6760
6761 static int
6762 cli_rule_file_process(const char *file_name,
6763 size_t line_len_max,
6764 struct table_rule_list **rule_list,
6765 uint32_t *n_rules,
6766 uint32_t *line_number,
6767 char *out,
6768 size_t out_size)
6769 {
6770 struct table_rule_list *list = NULL;
6771 char *line = NULL;
6772 FILE *f = NULL;
6773 uint32_t rule_id = 0, line_id = 0;
6774 int status = 0;
6775
6776 /* Check input arguments */
6777 if ((file_name == NULL) ||
6778 (strlen(file_name) == 0) ||
6779 (line_len_max == 0) ||
6780 (rule_list == NULL) ||
6781 (n_rules == NULL) ||
6782 (line_number == NULL) ||
6783 (out == NULL)) {
6784 status = -EINVAL;
6785 goto cli_rule_file_process_free;
6786 }
6787
6788 /* Memory allocation */
6789 list = malloc(sizeof(struct table_rule_list));
6790 if (list == NULL) {
6791 status = -ENOMEM;
6792 goto cli_rule_file_process_free;
6793 }
6794
6795 TAILQ_INIT(list);
6796
6797 line = malloc(line_len_max + 1);
6798 if (line == NULL) {
6799 status = -ENOMEM;
6800 goto cli_rule_file_process_free;
6801 }
6802
6803 /* Open file */
6804 f = fopen(file_name, "r");
6805 if (f == NULL) {
6806 status = -EIO;
6807 goto cli_rule_file_process_free;
6808 }
6809
6810 /* Read file */
6811 for (line_id = 1, rule_id = 0; ; line_id++) {
6812 char *tokens[CMD_MAX_TOKENS];
6813 struct table_rule *rule = NULL;
6814 uint32_t n_tokens, n_tokens_parsed, t0;
6815
6816 /* Read next line from file. */
6817 if (fgets(line, line_len_max + 1, f) == NULL)
6818 break;
6819
6820 /* Comment. */
6821 if (is_comment(line))
6822 continue;
6823
6824 /* Parse line. */
6825 n_tokens = RTE_DIM(tokens);
6826 status = parse_tokenize_string(line, tokens, &n_tokens);
6827 if (status) {
6828 status = -EINVAL;
6829 goto cli_rule_file_process_free;
6830 }
6831
6832 /* Empty line. */
6833 if (n_tokens == 0)
6834 continue;
6835 t0 = 0;
6836
6837 /* Rule alloc and insert. */
6838 rule = calloc(1, sizeof(struct table_rule));
6839 if (rule == NULL) {
6840 status = -ENOMEM;
6841 goto cli_rule_file_process_free;
6842 }
6843
6844 TAILQ_INSERT_TAIL(list, rule, node);
6845
6846 /* Rule match. */
6847 n_tokens_parsed = parse_match(tokens + t0,
6848 n_tokens - t0,
6849 out,
6850 out_size,
6851 &rule->match);
6852 if (n_tokens_parsed == 0) {
6853 status = -EINVAL;
6854 goto cli_rule_file_process_free;
6855 }
6856 t0 += n_tokens_parsed;
6857
6858 /* Rule action. */
6859 n_tokens_parsed = parse_table_action(tokens + t0,
6860 n_tokens - t0,
6861 out,
6862 out_size,
6863 &rule->action);
6864 if (n_tokens_parsed == 0) {
6865 status = -EINVAL;
6866 goto cli_rule_file_process_free;
6867 }
6868 t0 += n_tokens_parsed;
6869
6870 /* Line completed. */
6871 if (t0 < n_tokens) {
6872 status = -EINVAL;
6873 goto cli_rule_file_process_free;
6874 }
6875
6876 /* Increment rule count */
6877 rule_id++;
6878 }
6879
6880 /* Close file */
6881 fclose(f);
6882
6883 /* Memory free */
6884 free(line);
6885
6886 *rule_list = list;
6887 *n_rules = rule_id;
6888 *line_number = line_id;
6889 return 0;
6890
6891 cli_rule_file_process_free:
6892 if (rule_list != NULL)
6893 *rule_list = NULL;
6894
6895 if (n_rules != NULL)
6896 *n_rules = rule_id;
6897
6898 if (line_number != NULL)
6899 *line_number = line_id;
6900
6901 if (list != NULL)
6902 for ( ; ; ) {
6903 struct table_rule *rule;
6904
6905 rule = TAILQ_FIRST(list);
6906 if (rule == NULL)
6907 break;
6908
6909 TAILQ_REMOVE(list, rule, node);
6910 free(rule);
6911 }
6912
6913 if (f)
6914 fclose(f);
6915 free(line);
6916 free(list);
6917
6918 return status;
6919 }