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