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