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 #include <unistd.h>
10
11 #include <rte_common.h>
12 #include <rte_cycles.h>
13 #include <rte_string_fns.h>
14
15 #include "rte_eth_softnic_internals.h"
16
17 #ifndef CMD_MAX_TOKENS
18 #define CMD_MAX_TOKENS 256
19 #endif
20
21 #ifndef MAX_LINE_SIZE
22 #define MAX_LINE_SIZE 2048
23 #endif
24
25 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
26 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
27 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
28 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
29 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
30 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
31 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
32 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
33 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
34 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
35 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
36
37 static int
parser_read_uint64(uint64_t * value,char * p)38 parser_read_uint64(uint64_t *value, char *p)
39 {
40 uint64_t val = 0;
41
42 if (!value || !p || !p[0])
43 return -EINVAL;
44
45 val = strtoull(p, &p, 0);
46 if (p[0])
47 return -EINVAL;
48
49 *value = val;
50 return 0;
51 }
52
53 static int
parser_read_uint32(uint32_t * value,char * p)54 parser_read_uint32(uint32_t *value, char *p)
55 {
56 uint32_t val = 0;
57
58 if (!value || !p || !p[0])
59 return -EINVAL;
60
61 val = strtoul(p, &p, 0);
62 if (p[0])
63 return -EINVAL;
64
65 *value = val;
66 return 0;
67 }
68
69 #define PARSE_DELIMITER " \f\n\r\t\v"
70
71 static int
parse_tokenize_string(char * string,char * tokens[],uint32_t * n_tokens)72 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
73 {
74 uint32_t i;
75
76 if (!string || !tokens || !n_tokens || !*n_tokens)
77 return -EINVAL;
78
79 for (i = 0; i < *n_tokens; i++) {
80 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
81 if (!tokens[i])
82 break;
83 }
84
85 if (i == *n_tokens && strtok_r(string, PARSE_DELIMITER, &string))
86 return -E2BIG;
87
88 *n_tokens = i;
89 return 0;
90 }
91
92 static int
is_comment(char * in)93 is_comment(char *in)
94 {
95 if ((strlen(in) && index("!#%;", in[0])) ||
96 (strncmp(in, "//", 2) == 0) ||
97 (strncmp(in, "--", 2) == 0))
98 return 1;
99
100 return 0;
101 }
102
103 /**
104 * mempool <mempool_name>
105 * buffer <buffer_size>
106 * pool <pool_size>
107 * cache <cache_size>
108 */
109 static void
cmd_mempool(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)110 cmd_mempool(struct pmd_internals *softnic,
111 char **tokens,
112 uint32_t n_tokens,
113 char *out,
114 size_t out_size)
115 {
116 struct softnic_mempool_params p;
117 char *name;
118 struct softnic_mempool *mempool;
119
120 if (n_tokens != 8) {
121 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
122 return;
123 }
124
125 name = tokens[1];
126
127 if (strcmp(tokens[2], "buffer") != 0) {
128 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
129 return;
130 }
131
132 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
133 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
134 return;
135 }
136
137 if (strcmp(tokens[4], "pool") != 0) {
138 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
139 return;
140 }
141
142 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
143 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
144 return;
145 }
146
147 if (strcmp(tokens[6], "cache") != 0) {
148 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
149 return;
150 }
151
152 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
153 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
154 return;
155 }
156
157 mempool = softnic_mempool_create(softnic, name, &p);
158 if (mempool == NULL) {
159 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
160 return;
161 }
162 }
163
164 /**
165 * swq <swq_name>
166 * size <size>
167 */
168 static void
cmd_swq(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)169 cmd_swq(struct pmd_internals *softnic,
170 char **tokens,
171 uint32_t n_tokens,
172 char *out,
173 size_t out_size)
174 {
175 struct softnic_swq_params p;
176 char *name;
177 struct softnic_swq *swq;
178
179 if (n_tokens != 4) {
180 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
181 return;
182 }
183
184 name = tokens[1];
185
186 if (strcmp(tokens[2], "size") != 0) {
187 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
188 return;
189 }
190
191 if (parser_read_uint32(&p.size, tokens[3]) != 0) {
192 snprintf(out, out_size, MSG_ARG_INVALID, "size");
193 return;
194 }
195
196 swq = softnic_swq_create(softnic, name, &p);
197 if (swq == NULL) {
198 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
199 return;
200 }
201 }
202
203 /**
204 * pipeline codegen <spec_file> <code_file>
205 */
206 static void
cmd_softnic_pipeline_codegen(struct pmd_internals * softnic __rte_unused,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)207 cmd_softnic_pipeline_codegen(struct pmd_internals *softnic __rte_unused,
208 char **tokens,
209 uint32_t n_tokens,
210 char *out,
211 size_t out_size)
212 {
213 FILE *spec_file = NULL;
214 FILE *code_file = NULL;
215 uint32_t err_line;
216 const char *err_msg;
217 int status;
218
219 if (n_tokens != 4) {
220 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
221 return;
222 }
223
224 spec_file = fopen(tokens[2], "r");
225 if (!spec_file) {
226 snprintf(out, out_size, "Cannot open file %s.\n", tokens[2]);
227 return;
228 }
229
230 code_file = fopen(tokens[3], "w");
231 if (!code_file) {
232 snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
233 fclose(spec_file);
234 return;
235 }
236
237 status = rte_swx_pipeline_codegen(spec_file,
238 code_file,
239 &err_line,
240 &err_msg);
241
242 fclose(spec_file);
243 fclose(code_file);
244
245 if (status) {
246 snprintf(out, out_size, "Error %d at line %u: %s\n.",
247 status, err_line, err_msg);
248 return;
249 }
250 }
251
252 /**
253 * pipeline libbuild <code_file> <lib_file>
254 */
255 static void
cmd_softnic_pipeline_libbuild(struct pmd_internals * softnic __rte_unused,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)256 cmd_softnic_pipeline_libbuild(struct pmd_internals *softnic __rte_unused,
257 char **tokens,
258 uint32_t n_tokens,
259 char *out,
260 size_t out_size)
261 {
262 char *code_file, *lib_file, *obj_file = NULL, *log_file = NULL;
263 char *install_dir, *cwd = NULL, *buffer = NULL;
264 size_t length;
265 int status = 0;
266
267 if (n_tokens != 4) {
268 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
269 goto free;
270 }
271
272 install_dir = getenv("RTE_INSTALL_DIR");
273 if (!install_dir) {
274 cwd = malloc(MAX_LINE_SIZE);
275 if (!cwd) {
276 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
277 goto free;
278 }
279
280 install_dir = getcwd(cwd, MAX_LINE_SIZE);
281 if (!install_dir) {
282 snprintf(out, out_size, "Error: Path too long.\n");
283 goto free;
284 }
285 }
286
287 snprintf(out, out_size, "Using DPDK source code from \"%s\".\n", install_dir);
288 out_size -= strlen(out);
289 out += strlen(out);
290
291 code_file = tokens[2];
292 length = strnlen(code_file, MAX_LINE_SIZE);
293 if (length < 3 ||
294 code_file[length - 2] != '.' ||
295 code_file[length - 1] != 'c') {
296 snprintf(out, out_size, MSG_ARG_INVALID, "code_file");
297 goto free;
298 }
299
300 lib_file = tokens[3];
301 length = strnlen(lib_file, MAX_LINE_SIZE);
302 if (length < 4 ||
303 lib_file[length - 3] != '.' ||
304 lib_file[length - 2] != 's' ||
305 lib_file[length - 1] != 'o') {
306 snprintf(out, out_size, MSG_ARG_INVALID, "lib_file");
307 goto free;
308 }
309
310 obj_file = malloc(length);
311 log_file = malloc(length + 2);
312 if (!obj_file || !log_file) {
313 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
314 goto free;
315 }
316
317 memcpy(obj_file, lib_file, length - 2);
318 obj_file[length - 2] = 'o';
319 obj_file[length - 1] = 0;
320
321 memcpy(log_file, lib_file, length - 2);
322 log_file[length - 2] = 'l';
323 log_file[length - 1] = 'o';
324 log_file[length] = 'g';
325 log_file[length + 1] = 0;
326
327 buffer = malloc(MAX_LINE_SIZE);
328 if (!buffer) {
329 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
330 goto free;
331 }
332
333 snprintf(buffer,
334 MAX_LINE_SIZE,
335 "gcc -c -O3 -fpic -Wno-deprecated-declarations -o %s %s "
336 "-I %s/lib/pipeline "
337 "-I %s/lib/eal/include "
338 "-I %s/lib/eal/x86/include "
339 "-I %s/lib/eal/include/generic "
340 "-I %s/lib/log "
341 "-I %s/lib/meter "
342 "-I %s/lib/port "
343 "-I %s/lib/table "
344 "-I %s/lib/pipeline "
345 "-I %s/config "
346 "-I %s/build "
347 "-I %s/lib/eal/linux/include "
348 ">%s 2>&1 "
349 "&& "
350 "gcc -shared %s -o %s "
351 ">>%s 2>&1",
352 obj_file,
353 code_file,
354 install_dir,
355 install_dir,
356 install_dir,
357 install_dir,
358 install_dir,
359 install_dir,
360 install_dir,
361 install_dir,
362 install_dir,
363 install_dir,
364 install_dir,
365 install_dir,
366 log_file,
367 obj_file,
368 lib_file,
369 log_file);
370
371 status = system(buffer);
372 if (status) {
373 snprintf(out,
374 out_size,
375 "Library build failed, see file \"%s\" for details.\n",
376 log_file);
377 goto free;
378 }
379
380 free:
381 free(cwd);
382 free(obj_file);
383 free(log_file);
384 free(buffer);
385 }
386
387 /**
388 * pipeline <pipeline_name> build lib <lib_file> io <iospec_file> numa <numa_node>
389 */
390 static void
cmd_softnic_pipeline_build(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)391 cmd_softnic_pipeline_build(struct pmd_internals *softnic,
392 char **tokens,
393 uint32_t n_tokens,
394 char *out,
395 size_t out_size)
396 {
397 struct pipeline *p = NULL;
398 char *pipeline_name, *lib_file_name, *iospec_file_name;
399 uint32_t numa_node = 0;
400
401 /* Parsing. */
402 if (n_tokens != 9) {
403 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
404 return;
405 }
406
407 pipeline_name = tokens[1];
408
409 if (strcmp(tokens[2], "build")) {
410 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "build");
411 return;
412 }
413
414 if (strcmp(tokens[3], "lib")) {
415 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "lib");
416 return;
417 }
418
419 lib_file_name = tokens[4];
420
421 if (strcmp(tokens[5], "io")) {
422 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "io");
423 return;
424 }
425
426 iospec_file_name = tokens[6];
427
428 if (strcmp(tokens[7], "numa")) {
429 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
430 return;
431 }
432
433 if (parser_read_uint32(&numa_node, tokens[8])) {
434 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
435 return;
436 }
437
438 /* Pipeline create. */
439 p = softnic_pipeline_create(softnic,
440 pipeline_name,
441 lib_file_name,
442 iospec_file_name,
443 (int)numa_node);
444 if (!p)
445 snprintf(out, out_size, "Pipeline creation failed.\n");
446 }
447
448 static void
table_entry_free(struct rte_swx_table_entry * entry)449 table_entry_free(struct rte_swx_table_entry *entry)
450 {
451 if (!entry)
452 return;
453
454 free(entry->key);
455 free(entry->key_mask);
456 free(entry->action_data);
457 free(entry);
458 }
459
460 static int
pipeline_table_entries_add(struct rte_swx_ctl_pipeline * p,const char * table_name,FILE * file,uint32_t * file_line_number)461 pipeline_table_entries_add(struct rte_swx_ctl_pipeline *p,
462 const char *table_name,
463 FILE *file,
464 uint32_t *file_line_number)
465 {
466 char *line = NULL;
467 uint32_t line_id = 0;
468 int status = 0;
469
470 /* Buffer allocation. */
471 line = malloc(MAX_LINE_SIZE);
472 if (!line)
473 return -ENOMEM;
474
475 /* File read. */
476 for (line_id = 1; ; line_id++) {
477 struct rte_swx_table_entry *entry;
478 int is_blank_or_comment;
479
480 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
481 break;
482
483 entry = rte_swx_ctl_pipeline_table_entry_read(p,
484 table_name,
485 line,
486 &is_blank_or_comment);
487 if (!entry) {
488 if (is_blank_or_comment)
489 continue;
490
491 status = -EINVAL;
492 goto error;
493 }
494
495 status = rte_swx_ctl_pipeline_table_entry_add(p,
496 table_name,
497 entry);
498 table_entry_free(entry);
499 if (status)
500 goto error;
501 }
502
503 error:
504 free(line);
505 *file_line_number = line_id;
506 return status;
507 }
508
509 /**
510 * pipeline <pipeline_name> table <table_name> add <file_name>
511 */
512 static void
cmd_softnic_pipeline_table_add(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)513 cmd_softnic_pipeline_table_add(struct pmd_internals *softnic,
514 char **tokens,
515 uint32_t n_tokens,
516 char *out,
517 size_t out_size)
518 {
519 struct pipeline *p;
520 char *pipeline_name, *table_name, *file_name;
521 FILE *file = NULL;
522 uint32_t file_line_number = 0;
523 int status;
524
525 if (n_tokens != 6) {
526 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
527 return;
528 }
529
530 pipeline_name = tokens[1];
531 p = softnic_pipeline_find(softnic, pipeline_name);
532 if (!p) {
533 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
534 return;
535 }
536
537 table_name = tokens[3];
538
539 file_name = tokens[5];
540 file = fopen(file_name, "r");
541 if (!file) {
542 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
543 return;
544 }
545
546 status = pipeline_table_entries_add(p->ctl,
547 table_name,
548 file,
549 &file_line_number);
550 if (status)
551 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
552 file_name,
553 file_line_number);
554
555 fclose(file);
556 }
557
558 static int
pipeline_table_entries_delete(struct rte_swx_ctl_pipeline * p,const char * table_name,FILE * file,uint32_t * file_line_number)559 pipeline_table_entries_delete(struct rte_swx_ctl_pipeline *p,
560 const char *table_name,
561 FILE *file,
562 uint32_t *file_line_number)
563 {
564 char *line = NULL;
565 uint32_t line_id = 0;
566 int status = 0;
567
568 /* Buffer allocation. */
569 line = malloc(MAX_LINE_SIZE);
570 if (!line)
571 return -ENOMEM;
572
573 /* File read. */
574 for (line_id = 1; ; line_id++) {
575 struct rte_swx_table_entry *entry;
576 int is_blank_or_comment;
577
578 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
579 break;
580
581 entry = rte_swx_ctl_pipeline_table_entry_read(p,
582 table_name,
583 line,
584 &is_blank_or_comment);
585 if (!entry) {
586 if (is_blank_or_comment)
587 continue;
588
589 status = -EINVAL;
590 goto error;
591 }
592
593 status = rte_swx_ctl_pipeline_table_entry_delete(p,
594 table_name,
595 entry);
596 table_entry_free(entry);
597 if (status)
598 goto error;
599 }
600
601 error:
602 *file_line_number = line_id;
603 free(line);
604 return status;
605 }
606
607 /**
608 * pipeline <pipeline_name> table <table_name> delete <file_name>
609 */
610 static void
cmd_softnic_pipeline_table_delete(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)611 cmd_softnic_pipeline_table_delete(struct pmd_internals *softnic,
612 char **tokens,
613 uint32_t n_tokens,
614 char *out,
615 size_t out_size)
616 {
617 struct pipeline *p;
618 char *pipeline_name, *table_name, *file_name;
619 FILE *file = NULL;
620 uint32_t file_line_number = 0;
621 int status;
622
623 if (n_tokens != 6) {
624 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
625 return;
626 }
627
628 pipeline_name = tokens[1];
629 p = softnic_pipeline_find(softnic, pipeline_name);
630 if (!p) {
631 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
632 return;
633 }
634
635 table_name = tokens[3];
636
637 file_name = tokens[5];
638 file = fopen(file_name, "r");
639 if (!file) {
640 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
641 return;
642 }
643
644 status = pipeline_table_entries_delete(p->ctl,
645 table_name,
646 file,
647 &file_line_number);
648 if (status)
649 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
650 file_name,
651 file_line_number);
652
653 fclose(file);
654 }
655
656 static int
pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline * p,const char * table_name,FILE * file,uint32_t * file_line_number)657 pipeline_table_default_entry_add(struct rte_swx_ctl_pipeline *p,
658 const char *table_name,
659 FILE *file,
660 uint32_t *file_line_number)
661 {
662 char *line = NULL;
663 uint32_t line_id = 0;
664 int status = 0;
665
666 /* Buffer allocation. */
667 line = malloc(MAX_LINE_SIZE);
668 if (!line)
669 return -ENOMEM;
670
671 /* File read. */
672 for (line_id = 1; ; line_id++) {
673 struct rte_swx_table_entry *entry;
674 int is_blank_or_comment;
675
676 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
677 break;
678
679 entry = rte_swx_ctl_pipeline_table_entry_read(p,
680 table_name,
681 line,
682 &is_blank_or_comment);
683 if (!entry) {
684 if (is_blank_or_comment)
685 continue;
686
687 status = -EINVAL;
688 goto error;
689 }
690
691 status = rte_swx_ctl_pipeline_table_default_entry_add(p,
692 table_name,
693 entry);
694 table_entry_free(entry);
695 if (status)
696 goto error;
697 }
698
699 error:
700 *file_line_number = line_id;
701 free(line);
702 return status;
703 }
704
705 /**
706 * pipeline <pipeline_name> table <table_name> default <file_name>
707 */
708 static void
cmd_softnic_pipeline_table_default(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)709 cmd_softnic_pipeline_table_default(struct pmd_internals *softnic,
710 char **tokens,
711 uint32_t n_tokens,
712 char *out,
713 size_t out_size)
714 {
715 struct pipeline *p;
716 char *pipeline_name, *table_name, *file_name;
717 FILE *file = NULL;
718 uint32_t file_line_number = 0;
719 int status;
720
721 if (n_tokens != 6) {
722 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
723 return;
724 }
725
726 pipeline_name = tokens[1];
727 p = softnic_pipeline_find(softnic, pipeline_name);
728 if (!p) {
729 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
730 return;
731 }
732
733 table_name = tokens[3];
734
735 file_name = tokens[5];
736 file = fopen(file_name, "r");
737 if (!file) {
738 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
739 return;
740 }
741
742 status = pipeline_table_default_entry_add(p->ctl,
743 table_name,
744 file,
745 &file_line_number);
746 if (status)
747 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
748 file_name,
749 file_line_number);
750
751 fclose(file);
752 }
753
754 /**
755 * pipeline <pipeline_name> table <table_name> show [filename]
756 */
757 static void
cmd_softnic_pipeline_table_show(struct pmd_internals * softnic __rte_unused,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)758 cmd_softnic_pipeline_table_show(struct pmd_internals *softnic __rte_unused,
759 char **tokens,
760 uint32_t n_tokens,
761 char *out,
762 size_t out_size)
763 {
764 struct pipeline *p;
765 char *pipeline_name, *table_name;
766 FILE *file = NULL;
767 int status;
768
769 if (n_tokens != 5 && n_tokens != 6) {
770 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
771 return;
772 }
773
774 pipeline_name = tokens[1];
775 p = softnic_pipeline_find(softnic, pipeline_name);
776 if (!p) {
777 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
778 return;
779 }
780
781 table_name = tokens[3];
782 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
783 if (!file) {
784 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
785 return;
786 }
787
788 status = rte_swx_ctl_pipeline_table_fprintf(file, p->ctl, table_name);
789 if (status)
790 snprintf(out, out_size, MSG_ARG_INVALID, "table_name");
791
792 if (file)
793 fclose(file);
794 }
795
796 /**
797 * pipeline <pipeline_name> selector <selector_name> group add
798 */
799 static void
cmd_softnic_pipeline_selector_group_add(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)800 cmd_softnic_pipeline_selector_group_add(struct pmd_internals *softnic,
801 char **tokens,
802 uint32_t n_tokens,
803 char *out,
804 size_t out_size)
805 {
806 struct pipeline *p;
807 char *pipeline_name, *selector_name;
808 uint32_t group_id;
809 int status;
810
811 if (n_tokens != 6) {
812 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
813 return;
814 }
815
816 pipeline_name = tokens[1];
817 p = softnic_pipeline_find(softnic, pipeline_name);
818 if (!p) {
819 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
820 return;
821 }
822
823 if (strcmp(tokens[2], "selector") != 0) {
824 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
825 return;
826 }
827
828 selector_name = tokens[3];
829
830 if (strcmp(tokens[4], "group") ||
831 strcmp(tokens[5], "add")) {
832 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group add");
833 return;
834 }
835
836 status = rte_swx_ctl_pipeline_selector_group_add(p->ctl,
837 selector_name,
838 &group_id);
839 if (status)
840 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
841 else
842 snprintf(out, out_size, "Group ID: %u\n", group_id);
843 }
844
845 /**
846 * pipeline <pipeline_name> selector <selector_name> group delete <group_id>
847 */
848 static void
cmd_softnic_pipeline_selector_group_delete(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)849 cmd_softnic_pipeline_selector_group_delete(struct pmd_internals *softnic,
850 char **tokens,
851 uint32_t n_tokens,
852 char *out,
853 size_t out_size)
854 {
855 struct pipeline *p;
856 char *pipeline_name, *selector_name;
857 uint32_t group_id;
858 int status;
859
860 if (n_tokens != 7) {
861 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
862 return;
863 }
864
865 pipeline_name = tokens[1];
866 p = softnic_pipeline_find(softnic, pipeline_name);
867 if (!p) {
868 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
869 return;
870 }
871
872 if (strcmp(tokens[2], "selector") != 0) {
873 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
874 return;
875 }
876
877 selector_name = tokens[3];
878
879 if (strcmp(tokens[4], "group") ||
880 strcmp(tokens[5], "delete")) {
881 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group delete");
882 return;
883 }
884
885 if (parser_read_uint32(&group_id, tokens[6]) != 0) {
886 snprintf(out, out_size, MSG_ARG_INVALID, "group_id");
887 return;
888 }
889
890 status = rte_swx_ctl_pipeline_selector_group_delete(p->ctl,
891 selector_name,
892 group_id);
893 if (status)
894 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
895 }
896
897 #define GROUP_MEMBER_INFO_TOKENS_MAX 6
898
899 static int
token_is_comment(const char * token)900 token_is_comment(const char *token)
901 {
902 if ((token[0] == '#') ||
903 (token[0] == ';') ||
904 ((token[0] == '/') && (token[1] == '/')))
905 return 1; /* TRUE. */
906
907 return 0; /* FALSE. */
908 }
909
910 static int
pipeline_selector_group_member_read(const char * string,uint32_t * group_id,uint32_t * member_id,uint32_t * weight,int * is_blank_or_comment)911 pipeline_selector_group_member_read(const char *string,
912 uint32_t *group_id,
913 uint32_t *member_id,
914 uint32_t *weight,
915 int *is_blank_or_comment)
916 {
917 char *token_array[GROUP_MEMBER_INFO_TOKENS_MAX], **tokens;
918 char *s0 = NULL, *s;
919 uint32_t n_tokens = 0, group_id_val = 0, member_id_val = 0, weight_val = 0;
920 int blank_or_comment = 0;
921
922 /* Check input arguments. */
923 if (!string || !string[0])
924 goto error;
925
926 /* Memory allocation. */
927 s0 = strdup(string);
928 if (!s0)
929 goto error;
930
931 /* Parse the string into tokens. */
932 for (s = s0; ; ) {
933 char *token;
934
935 token = strtok_r(s, " \f\n\r\t\v", &s);
936 if (!token || token_is_comment(token))
937 break;
938
939 if (n_tokens >= GROUP_MEMBER_INFO_TOKENS_MAX)
940 goto error;
941
942 token_array[n_tokens] = token;
943 n_tokens++;
944 }
945
946 if (!n_tokens) {
947 blank_or_comment = 1;
948 goto error;
949 }
950
951 tokens = token_array;
952
953 if (n_tokens < 4 ||
954 strcmp(tokens[0], "group") ||
955 strcmp(tokens[2], "member"))
956 goto error;
957
958 /*
959 * Group ID.
960 */
961 if (parser_read_uint32(&group_id_val, tokens[1]) != 0)
962 goto error;
963 *group_id = group_id_val;
964
965 /*
966 * Member ID.
967 */
968 if (parser_read_uint32(&member_id_val, tokens[3]) != 0)
969 goto error;
970 *member_id = member_id_val;
971
972 tokens += 4;
973 n_tokens -= 4;
974
975 /*
976 * Weight.
977 */
978 if (n_tokens && !strcmp(tokens[0], "weight")) {
979 if (n_tokens < 2)
980 goto error;
981
982 if (parser_read_uint32(&weight_val, tokens[1]) != 0)
983 goto error;
984 *weight = weight_val;
985
986 tokens += 2;
987 n_tokens -= 2;
988 }
989
990 if (n_tokens)
991 goto error;
992
993 free(s0);
994 return 0;
995
996 error:
997 free(s0);
998 if (is_blank_or_comment)
999 *is_blank_or_comment = blank_or_comment;
1000 return -EINVAL;
1001 }
1002
1003 static int
pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline * p,const char * selector_name,FILE * file,uint32_t * file_line_number)1004 pipeline_selector_group_members_add(struct rte_swx_ctl_pipeline *p,
1005 const char *selector_name,
1006 FILE *file,
1007 uint32_t *file_line_number)
1008 {
1009 char *line = NULL;
1010 uint32_t line_id = 0;
1011 int status = 0;
1012
1013 /* Buffer allocation. */
1014 line = malloc(MAX_LINE_SIZE);
1015 if (!line)
1016 return -ENOMEM;
1017
1018 /* File read. */
1019 for (line_id = 1; ; line_id++) {
1020 uint32_t group_id, member_id, weight;
1021 int is_blank_or_comment;
1022
1023 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
1024 break;
1025
1026 status = pipeline_selector_group_member_read(line,
1027 &group_id,
1028 &member_id,
1029 &weight,
1030 &is_blank_or_comment);
1031 if (status) {
1032 if (is_blank_or_comment)
1033 continue;
1034
1035 goto error;
1036 }
1037
1038 status = rte_swx_ctl_pipeline_selector_group_member_add(p,
1039 selector_name,
1040 group_id,
1041 member_id,
1042 weight);
1043 if (status)
1044 goto error;
1045 }
1046
1047 error:
1048 free(line);
1049 *file_line_number = line_id;
1050 return status;
1051 }
1052
1053 /**
1054 * pipeline <pipeline_name> selector <selector_name> group member add <file_name>
1055 */
1056 static void
cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1057 cmd_softnic_pipeline_selector_group_member_add(struct pmd_internals *softnic,
1058 char **tokens,
1059 uint32_t n_tokens,
1060 char *out,
1061 size_t out_size)
1062 {
1063 struct pipeline *p;
1064 char *pipeline_name, *selector_name, *file_name;
1065 FILE *file = NULL;
1066 uint32_t file_line_number = 0;
1067 int status;
1068
1069 if (n_tokens != 8) {
1070 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1071 return;
1072 }
1073
1074 pipeline_name = tokens[1];
1075 p = softnic_pipeline_find(softnic, pipeline_name);
1076 if (!p) {
1077 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1078 return;
1079 }
1080
1081 if (strcmp(tokens[2], "selector") != 0) {
1082 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
1083 return;
1084 }
1085
1086 selector_name = tokens[3];
1087
1088 if (strcmp(tokens[4], "group") ||
1089 strcmp(tokens[5], "member") ||
1090 strcmp(tokens[6], "add")) {
1091 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member add");
1092 return;
1093 }
1094
1095 file_name = tokens[7];
1096 file = fopen(file_name, "r");
1097 if (!file) {
1098 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
1099 return;
1100 }
1101
1102 status = pipeline_selector_group_members_add(p->ctl,
1103 selector_name,
1104 file,
1105 &file_line_number);
1106 if (status)
1107 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
1108 file_name,
1109 file_line_number);
1110
1111 fclose(file);
1112 }
1113
1114 static int
pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline * p,const char * selector_name,FILE * file,uint32_t * file_line_number)1115 pipeline_selector_group_members_delete(struct rte_swx_ctl_pipeline *p,
1116 const char *selector_name,
1117 FILE *file,
1118 uint32_t *file_line_number)
1119 {
1120 char *line = NULL;
1121 uint32_t line_id = 0;
1122 int status = 0;
1123
1124 /* Buffer allocation. */
1125 line = malloc(MAX_LINE_SIZE);
1126 if (!line)
1127 return -ENOMEM;
1128
1129 /* File read. */
1130 for (line_id = 1; ; line_id++) {
1131 uint32_t group_id, member_id, weight;
1132 int is_blank_or_comment;
1133
1134 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
1135 break;
1136
1137 status = pipeline_selector_group_member_read(line,
1138 &group_id,
1139 &member_id,
1140 &weight,
1141 &is_blank_or_comment);
1142 if (status) {
1143 if (is_blank_or_comment)
1144 continue;
1145
1146 goto error;
1147 }
1148
1149 status = rte_swx_ctl_pipeline_selector_group_member_delete(p,
1150 selector_name,
1151 group_id,
1152 member_id);
1153 if (status)
1154 goto error;
1155 }
1156
1157 error:
1158 free(line);
1159 *file_line_number = line_id;
1160 return status;
1161 }
1162
1163 /**
1164 * pipeline <pipeline_name> selector <selector_name> group member delete <file_name>
1165 */
1166 static void
cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1167 cmd_softnic_pipeline_selector_group_member_delete(struct pmd_internals *softnic,
1168 char **tokens,
1169 uint32_t n_tokens,
1170 char *out,
1171 size_t out_size)
1172 {
1173 struct pipeline *p;
1174 char *pipeline_name, *selector_name, *file_name;
1175 FILE *file = NULL;
1176 uint32_t file_line_number = 0;
1177 int status;
1178
1179 if (n_tokens != 8) {
1180 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1181 return;
1182 }
1183
1184 pipeline_name = tokens[1];
1185 p = softnic_pipeline_find(softnic, pipeline_name);
1186 if (!p) {
1187 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1188 return;
1189 }
1190
1191 if (strcmp(tokens[2], "selector") != 0) {
1192 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "selector");
1193 return;
1194 }
1195
1196 selector_name = tokens[3];
1197
1198 if (strcmp(tokens[4], "group") ||
1199 strcmp(tokens[5], "member") ||
1200 strcmp(tokens[6], "delete")) {
1201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group member delete");
1202 return;
1203 }
1204
1205 file_name = tokens[7];
1206 file = fopen(file_name, "r");
1207 if (!file) {
1208 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
1209 return;
1210 }
1211
1212 status = pipeline_selector_group_members_delete(p->ctl,
1213 selector_name,
1214 file,
1215 &file_line_number);
1216 if (status)
1217 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
1218 file_name,
1219 file_line_number);
1220
1221 fclose(file);
1222 }
1223
1224 /**
1225 * pipeline <pipeline_name> selector <selector_name> show [filename]
1226 */
1227 static void
cmd_softnic_pipeline_selector_show(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1228 cmd_softnic_pipeline_selector_show(struct pmd_internals *softnic,
1229 char **tokens,
1230 uint32_t n_tokens,
1231 char *out,
1232 size_t out_size)
1233 {
1234 struct pipeline *p;
1235 char *pipeline_name, *selector_name;
1236 FILE *file = NULL;
1237 int status;
1238
1239 if (n_tokens != 5 && n_tokens != 6) {
1240 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1241 return;
1242 }
1243
1244 pipeline_name = tokens[1];
1245 p = softnic_pipeline_find(softnic, pipeline_name);
1246 if (!p) {
1247 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1248 return;
1249 }
1250
1251 selector_name = tokens[3];
1252
1253 file = (n_tokens == 6) ? fopen(tokens[5], "w") : stdout;
1254 if (!file) {
1255 snprintf(out, out_size, "Cannot open file %s.\n", tokens[5]);
1256 return;
1257 }
1258
1259 status = rte_swx_ctl_pipeline_selector_fprintf(file, p->ctl, selector_name);
1260 if (status)
1261 snprintf(out, out_size, MSG_ARG_INVALID, "selector_name");
1262
1263 if (file)
1264 fclose(file);
1265 }
1266
1267 static int
pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline * p,const char * learner_name,FILE * file,uint32_t * file_line_number)1268 pipeline_learner_default_entry_add(struct rte_swx_ctl_pipeline *p,
1269 const char *learner_name,
1270 FILE *file,
1271 uint32_t *file_line_number)
1272 {
1273 char *line = NULL;
1274 uint32_t line_id = 0;
1275 int status = 0;
1276
1277 /* Buffer allocation. */
1278 line = malloc(MAX_LINE_SIZE);
1279 if (!line)
1280 return -ENOMEM;
1281
1282 /* File read. */
1283 for (line_id = 1; ; line_id++) {
1284 struct rte_swx_table_entry *entry;
1285 int is_blank_or_comment;
1286
1287 if (fgets(line, MAX_LINE_SIZE, file) == NULL)
1288 break;
1289
1290 entry = rte_swx_ctl_pipeline_learner_default_entry_read(p,
1291 learner_name,
1292 line,
1293 &is_blank_or_comment);
1294 if (!entry) {
1295 if (is_blank_or_comment)
1296 continue;
1297
1298 status = -EINVAL;
1299 goto error;
1300 }
1301
1302 status = rte_swx_ctl_pipeline_learner_default_entry_add(p,
1303 learner_name,
1304 entry);
1305 table_entry_free(entry);
1306 if (status)
1307 goto error;
1308 }
1309
1310 error:
1311 *file_line_number = line_id;
1312 free(line);
1313 return status;
1314 }
1315
1316 /**
1317 * pipeline <pipeline_name> learner <learner_name> default <file_name>
1318 */
1319 static void
cmd_softnic_pipeline_learner_default(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1320 cmd_softnic_pipeline_learner_default(struct pmd_internals *softnic,
1321 char **tokens,
1322 uint32_t n_tokens,
1323 char *out,
1324 size_t out_size)
1325 {
1326 struct pipeline *p;
1327 char *pipeline_name, *learner_name, *file_name;
1328 FILE *file = NULL;
1329 uint32_t file_line_number = 0;
1330 int status;
1331
1332 if (n_tokens != 6) {
1333 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1334 return;
1335 }
1336
1337 pipeline_name = tokens[1];
1338 p = softnic_pipeline_find(softnic, pipeline_name);
1339 if (!p) {
1340 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1341 return;
1342 }
1343
1344 learner_name = tokens[3];
1345
1346 file_name = tokens[5];
1347 file = fopen(file_name, "r");
1348 if (!file) {
1349 snprintf(out, out_size, "Cannot open file %s.\n", file_name);
1350 return;
1351 }
1352
1353 status = pipeline_learner_default_entry_add(p->ctl,
1354 learner_name,
1355 file,
1356 &file_line_number);
1357 if (status)
1358 snprintf(out, out_size, "Invalid entry in file %s at line %u\n",
1359 file_name,
1360 file_line_number);
1361
1362 fclose(file);
1363 }
1364
1365 /**
1366 * pipeline <pipeline_name> commit
1367 */
1368 static void
cmd_softnic_pipeline_commit(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1369 cmd_softnic_pipeline_commit(struct pmd_internals *softnic,
1370 char **tokens,
1371 uint32_t n_tokens,
1372 char *out,
1373 size_t out_size)
1374 {
1375 struct pipeline *p;
1376 char *pipeline_name;
1377 int status;
1378
1379 if (n_tokens != 3) {
1380 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1381 return;
1382 }
1383
1384 pipeline_name = tokens[1];
1385 p = softnic_pipeline_find(softnic, pipeline_name);
1386 if (!p) {
1387 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1388 return;
1389 }
1390
1391 status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
1392 if (status)
1393 snprintf(out, out_size, "Commit failed. "
1394 "Use \"commit\" to retry or \"abort\" to discard the pending work.\n");
1395 }
1396
1397 /**
1398 * pipeline <pipeline_name> abort
1399 */
1400 static void
cmd_softnic_pipeline_abort(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1401 cmd_softnic_pipeline_abort(struct pmd_internals *softnic,
1402 char **tokens,
1403 uint32_t n_tokens,
1404 char *out,
1405 size_t out_size)
1406 {
1407 struct pipeline *p;
1408 char *pipeline_name;
1409
1410 if (n_tokens != 3) {
1411 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1412 return;
1413 }
1414
1415 pipeline_name = tokens[1];
1416 p = softnic_pipeline_find(softnic, pipeline_name);
1417 if (!p) {
1418 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1419 return;
1420 }
1421
1422 rte_swx_ctl_pipeline_abort(p->ctl);
1423 }
1424
1425 /**
1426 * pipeline <pipeline_name> regrd <register_array_name> <index>
1427 */
1428 static void
cmd_softnic_pipeline_regrd(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1429 cmd_softnic_pipeline_regrd(struct pmd_internals *softnic,
1430 char **tokens,
1431 uint32_t n_tokens,
1432 char *out,
1433 size_t out_size)
1434 {
1435 struct pipeline *p;
1436 const char *pipeline_name, *name;
1437 uint64_t value;
1438 uint32_t idx;
1439 int status;
1440
1441 if (n_tokens != 5) {
1442 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1443 return;
1444 }
1445
1446 pipeline_name = tokens[1];
1447 p = softnic_pipeline_find(softnic, pipeline_name);
1448 if (!p) {
1449 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1450 return;
1451 }
1452
1453 if (strcmp(tokens[2], "regrd")) {
1454 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
1455 return;
1456 }
1457
1458 name = tokens[3];
1459
1460 if (parser_read_uint32(&idx, tokens[4])) {
1461 snprintf(out, out_size, MSG_ARG_INVALID, "index");
1462 return;
1463 }
1464
1465 status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
1466 if (status) {
1467 snprintf(out, out_size, "Command failed.\n");
1468 return;
1469 }
1470
1471 snprintf(out, out_size, "0x%" PRIx64 "\n", value);
1472 }
1473
1474 /**
1475 * pipeline <pipeline_name> regwr <register_array_name> <index> <value>
1476 */
1477 static void
cmd_softnic_pipeline_regwr(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1478 cmd_softnic_pipeline_regwr(struct pmd_internals *softnic,
1479 char **tokens,
1480 uint32_t n_tokens,
1481 char *out,
1482 size_t out_size)
1483 {
1484 struct pipeline *p;
1485 const char *pipeline_name, *name;
1486 uint64_t value;
1487 uint32_t idx;
1488 int status;
1489
1490 if (n_tokens != 6) {
1491 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1492 return;
1493 }
1494
1495 pipeline_name = tokens[1];
1496 p = softnic_pipeline_find(softnic, pipeline_name);
1497 if (!p) {
1498 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1499 return;
1500 }
1501
1502 if (strcmp(tokens[2], "regwr")) {
1503 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
1504 return;
1505 }
1506
1507 name = tokens[3];
1508
1509 if (parser_read_uint32(&idx, tokens[4])) {
1510 snprintf(out, out_size, MSG_ARG_INVALID, "index");
1511 return;
1512 }
1513
1514 if (parser_read_uint64(&value, tokens[5])) {
1515 snprintf(out, out_size, MSG_ARG_INVALID, "value");
1516 return;
1517 }
1518
1519 status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
1520 if (status) {
1521 snprintf(out, out_size, "Command failed.\n");
1522 return;
1523 }
1524 }
1525
1526 /**
1527 * pipeline <pipeline_name> meter profile <profile_name> add cir <cir> pir <pir> cbs <cbs> pbs <pbs>
1528 */
1529 static void
cmd_softnic_pipeline_meter_profile_add(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1530 cmd_softnic_pipeline_meter_profile_add(struct pmd_internals *softnic,
1531 char **tokens,
1532 uint32_t n_tokens,
1533 char *out,
1534 size_t out_size)
1535 {
1536 struct rte_meter_trtcm_params params;
1537 struct pipeline *p;
1538 const char *profile_name;
1539 int status;
1540
1541 if (n_tokens != 14) {
1542 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1543 return;
1544 }
1545
1546 p = softnic_pipeline_find(softnic, tokens[1]);
1547 if (!p) {
1548 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1549 return;
1550 }
1551
1552 if (strcmp(tokens[2], "meter")) {
1553 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
1554 return;
1555 }
1556
1557 if (strcmp(tokens[3], "profile")) {
1558 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
1559 return;
1560 }
1561
1562 profile_name = tokens[4];
1563
1564 if (strcmp(tokens[5], "add")) {
1565 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
1566 return;
1567 }
1568
1569 if (strcmp(tokens[6], "cir")) {
1570 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
1571 return;
1572 }
1573
1574 if (parser_read_uint64(¶ms.cir, tokens[7])) {
1575 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
1576 return;
1577 }
1578
1579 if (strcmp(tokens[8], "pir")) {
1580 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
1581 return;
1582 }
1583
1584 if (parser_read_uint64(¶ms.pir, tokens[9])) {
1585 snprintf(out, out_size, MSG_ARG_INVALID, "pir");
1586 return;
1587 }
1588
1589 if (strcmp(tokens[10], "cbs")) {
1590 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
1591 return;
1592 }
1593
1594 if (parser_read_uint64(¶ms.cbs, tokens[11])) {
1595 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
1596 return;
1597 }
1598
1599 if (strcmp(tokens[12], "pbs")) {
1600 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
1601 return;
1602 }
1603
1604 if (parser_read_uint64(¶ms.pbs, tokens[13])) {
1605 snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
1606 return;
1607 }
1608
1609 status = rte_swx_ctl_meter_profile_add(p->p, profile_name, ¶ms);
1610 if (status) {
1611 snprintf(out, out_size, "Command failed.\n");
1612 return;
1613 }
1614 }
1615
1616 /**
1617 * pipeline <pipeline_name> meter profile <profile_name> delete
1618 */
1619 static void
cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1620 cmd_softnic_pipeline_meter_profile_delete(struct pmd_internals *softnic,
1621 char **tokens,
1622 uint32_t n_tokens,
1623 char *out,
1624 size_t out_size)
1625 {
1626 struct pipeline *p;
1627 const char *profile_name;
1628 int status;
1629
1630 if (n_tokens != 6) {
1631 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1632 return;
1633 }
1634
1635 p = softnic_pipeline_find(softnic, tokens[1]);
1636 if (!p) {
1637 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1638 return;
1639 }
1640
1641 if (strcmp(tokens[2], "meter")) {
1642 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
1643 return;
1644 }
1645
1646 if (strcmp(tokens[3], "profile")) {
1647 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
1648 return;
1649 }
1650
1651 profile_name = tokens[4];
1652
1653 if (strcmp(tokens[5], "delete")) {
1654 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
1655 return;
1656 }
1657
1658 status = rte_swx_ctl_meter_profile_delete(p->p, profile_name);
1659 if (status) {
1660 snprintf(out, out_size, "Command failed.\n");
1661 return;
1662 }
1663 }
1664
1665 /**
1666 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> reset
1667 */
1668 static void
cmd_softnic_pipeline_meter_reset(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1669 cmd_softnic_pipeline_meter_reset(struct pmd_internals *softnic,
1670 char **tokens,
1671 uint32_t n_tokens,
1672 char *out,
1673 size_t out_size)
1674 {
1675 struct pipeline *p;
1676 const char *name;
1677 uint32_t idx0 = 0, idx1 = 0;
1678
1679 if (n_tokens != 9) {
1680 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1681 return;
1682 }
1683
1684 p = softnic_pipeline_find(softnic, tokens[1]);
1685 if (!p) {
1686 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1687 return;
1688 }
1689
1690 if (strcmp(tokens[2], "meter")) {
1691 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
1692 return;
1693 }
1694
1695 name = tokens[3];
1696
1697 if (strcmp(tokens[4], "from")) {
1698 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
1699 return;
1700 }
1701
1702 if (parser_read_uint32(&idx0, tokens[5])) {
1703 snprintf(out, out_size, MSG_ARG_INVALID, "index0");
1704 return;
1705 }
1706
1707 if (strcmp(tokens[6], "to")) {
1708 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
1709 return;
1710 }
1711
1712 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
1713 snprintf(out, out_size, MSG_ARG_INVALID, "index1");
1714 return;
1715 }
1716
1717 if (strcmp(tokens[8], "reset")) {
1718 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "reset");
1719 return;
1720 }
1721
1722 for ( ; idx0 <= idx1; idx0++) {
1723 int status;
1724
1725 status = rte_swx_ctl_meter_reset(p->p, name, idx0);
1726 if (status) {
1727 snprintf(out, out_size, "Command failed for index %u.\n", idx0);
1728 return;
1729 }
1730 }
1731 }
1732
1733 /**
1734 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> set
1735 * profile <profile_name>
1736 */
1737 static void
cmd_softnic_pipeline_meter_set(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1738 cmd_softnic_pipeline_meter_set(struct pmd_internals *softnic,
1739 char **tokens,
1740 uint32_t n_tokens,
1741 char *out,
1742 size_t out_size)
1743 {
1744 struct pipeline *p;
1745 const char *name, *profile_name;
1746 uint32_t idx0 = 0, idx1 = 0;
1747
1748 if (n_tokens != 11) {
1749 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1750 return;
1751 }
1752
1753 p = softnic_pipeline_find(softnic, tokens[1]);
1754 if (!p) {
1755 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1756 return;
1757 }
1758
1759 if (strcmp(tokens[2], "meter")) {
1760 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
1761 return;
1762 }
1763
1764 name = tokens[3];
1765
1766 if (strcmp(tokens[4], "from")) {
1767 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
1768 return;
1769 }
1770
1771 if (parser_read_uint32(&idx0, tokens[5])) {
1772 snprintf(out, out_size, MSG_ARG_INVALID, "index0");
1773 return;
1774 }
1775
1776 if (strcmp(tokens[6], "to")) {
1777 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
1778 return;
1779 }
1780
1781 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
1782 snprintf(out, out_size, MSG_ARG_INVALID, "index1");
1783 return;
1784 }
1785
1786 if (strcmp(tokens[8], "set")) {
1787 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "set");
1788 return;
1789 }
1790
1791 if (strcmp(tokens[9], "profile")) {
1792 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
1793 return;
1794 }
1795
1796 profile_name = tokens[10];
1797
1798 for ( ; idx0 <= idx1; idx0++) {
1799 int status;
1800
1801 status = rte_swx_ctl_meter_set(p->p, name, idx0, profile_name);
1802 if (status) {
1803 snprintf(out, out_size, "Command failed for index %u.\n", idx0);
1804 return;
1805 }
1806 }
1807 }
1808
1809 /**
1810 * pipeline <pipeline_name> meter <meter_array_name> from <index0> to <index1> stats
1811 */
1812 static void
cmd_softnic_pipeline_meter_stats(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1813 cmd_softnic_pipeline_meter_stats(struct pmd_internals *softnic,
1814 char **tokens,
1815 uint32_t n_tokens,
1816 char *out,
1817 size_t out_size)
1818 {
1819 struct rte_swx_ctl_meter_stats stats;
1820 struct pipeline *p;
1821 const char *name;
1822 uint32_t idx0 = 0, idx1 = 0;
1823
1824 if (n_tokens != 9) {
1825 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1826 return;
1827 }
1828
1829 p = softnic_pipeline_find(softnic, tokens[1]);
1830 if (!p) {
1831 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1832 return;
1833 }
1834
1835 if (strcmp(tokens[2], "meter")) {
1836 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
1837 return;
1838 }
1839
1840 name = tokens[3];
1841
1842 if (strcmp(tokens[4], "from")) {
1843 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
1844 return;
1845 }
1846
1847 if (parser_read_uint32(&idx0, tokens[5])) {
1848 snprintf(out, out_size, MSG_ARG_INVALID, "index0");
1849 return;
1850 }
1851
1852 if (strcmp(tokens[6], "to")) {
1853 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
1854 return;
1855 }
1856
1857 if (parser_read_uint32(&idx1, tokens[7]) || idx1 < idx0) {
1858 snprintf(out, out_size, MSG_ARG_INVALID, "index1");
1859 return;
1860 }
1861
1862 if (strcmp(tokens[8], "stats")) {
1863 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1864 return;
1865 }
1866
1867 /* Table header. */
1868 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
1869 "-------",
1870 "----------------", "----------------", "----------------",
1871 "----------------", "----------------", "----------------");
1872 out_size -= strlen(out);
1873 out += strlen(out);
1874
1875 snprintf(out, out_size, "| %4s | %16s | %16s | %16s | %16s | %16s | %16s |\n",
1876 "METER #",
1877 "GREEN (packets)", "YELLOW (packets)", "RED (packets)",
1878 "GREEN (bytes)", "YELLOW (bytes)", "RED (bytes)");
1879 out_size -= strlen(out);
1880 out += strlen(out);
1881
1882 snprintf(out, out_size, "+-%7s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+-%16s-+\n",
1883 "-------",
1884 "----------------", "----------------", "----------------",
1885 "----------------", "----------------", "----------------");
1886 out_size -= strlen(out);
1887 out += strlen(out);
1888
1889 /* Table rows. */
1890 for ( ; idx0 <= idx1; idx0++) {
1891 int status;
1892
1893 status = rte_swx_ctl_meter_stats_read(p->p, name, idx0, &stats);
1894 if (status) {
1895 snprintf(out, out_size, "Pipeline meter stats error at index %u.\n", idx0);
1896 out_size -= strlen(out);
1897 out += strlen(out);
1898 return;
1899 }
1900
1901 snprintf(out, out_size, "| %7d | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64
1902 " | %16" PRIx64 " | %16" PRIx64 " | %16" PRIx64 " |\n",
1903 idx0,
1904 stats.n_pkts[RTE_COLOR_GREEN],
1905 stats.n_pkts[RTE_COLOR_YELLOW],
1906 stats.n_pkts[RTE_COLOR_RED],
1907 stats.n_bytes[RTE_COLOR_GREEN],
1908 stats.n_bytes[RTE_COLOR_YELLOW],
1909 stats.n_bytes[RTE_COLOR_RED]);
1910 out_size -= strlen(out);
1911 out += strlen(out);
1912 }
1913 }
1914
1915 /**
1916 * pipeline <pipeline_name> stats
1917 */
1918 static void
cmd_softnic_pipeline_stats(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)1919 cmd_softnic_pipeline_stats(struct pmd_internals *softnic,
1920 char **tokens,
1921 uint32_t n_tokens,
1922 char *out,
1923 size_t out_size)
1924 {
1925 struct rte_swx_ctl_pipeline_info info;
1926 struct pipeline *p;
1927 uint32_t i;
1928 int status;
1929
1930 if (n_tokens != 3) {
1931 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1932 return;
1933 }
1934
1935 p = softnic_pipeline_find(softnic, tokens[1]);
1936 if (!p) {
1937 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1938 return;
1939 }
1940
1941 if (strcmp(tokens[2], "stats")) {
1942 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1943 return;
1944 }
1945
1946 status = rte_swx_ctl_pipeline_info_get(p->p, &info);
1947 if (status) {
1948 snprintf(out, out_size, "Pipeline info get error.");
1949 return;
1950 }
1951
1952 snprintf(out, out_size, "Input ports:\n");
1953 out_size -= strlen(out);
1954 out += strlen(out);
1955
1956 for (i = 0; i < info.n_ports_in; i++) {
1957 struct rte_swx_port_in_stats stats;
1958
1959 rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
1960
1961 snprintf(out, out_size, "\tPort %u:"
1962 " packets %" PRIu64
1963 " bytes %" PRIu64
1964 " empty %" PRIu64 "\n",
1965 i, stats.n_pkts, stats.n_bytes, stats.n_empty);
1966 out_size -= strlen(out);
1967 out += strlen(out);
1968 }
1969
1970 snprintf(out, out_size, "\nOutput ports:\n");
1971 out_size -= strlen(out);
1972 out += strlen(out);
1973
1974 for (i = 0; i < info.n_ports_out; i++) {
1975 struct rte_swx_port_out_stats stats;
1976
1977 rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
1978
1979 if (i != info.n_ports_out - 1)
1980 snprintf(out, out_size, "\tPort %u:", i);
1981 else
1982 snprintf(out, out_size, "\tDROP:");
1983
1984 out_size -= strlen(out);
1985 out += strlen(out);
1986
1987 snprintf(out,
1988 out_size,
1989 " packets %" PRIu64
1990 " bytes %" PRIu64
1991 " packets dropped %" PRIu64
1992 " bytes dropped %" PRIu64
1993 " clone %" PRIu64
1994 " clonerr %" PRIu64 "\n",
1995 stats.n_pkts,
1996 stats.n_bytes,
1997 stats.n_pkts_drop,
1998 stats.n_bytes_drop,
1999 stats.n_pkts_clone,
2000 stats.n_pkts_clone_err);
2001
2002 out_size -= strlen(out);
2003 out += strlen(out);
2004 }
2005
2006 snprintf(out, out_size, "\nTables:\n");
2007 out_size -= strlen(out);
2008 out += strlen(out);
2009
2010 for (i = 0; i < info.n_tables; i++) {
2011 struct rte_swx_ctl_table_info table_info;
2012 uint64_t n_pkts_action[info.n_actions];
2013 struct rte_swx_table_stats stats = {
2014 .n_pkts_hit = 0,
2015 .n_pkts_miss = 0,
2016 .n_pkts_action = n_pkts_action,
2017 };
2018 uint32_t j;
2019
2020 status = rte_swx_ctl_table_info_get(p->p, i, &table_info);
2021 if (status) {
2022 snprintf(out, out_size, "Table info get error.");
2023 return;
2024 }
2025
2026 status = rte_swx_ctl_pipeline_table_stats_read(p->p, table_info.name, &stats);
2027 if (status) {
2028 snprintf(out, out_size, "Table stats read error.");
2029 return;
2030 }
2031
2032 snprintf(out, out_size, "\tTable %s:\n"
2033 "\t\tHit (packets): %" PRIu64 "\n"
2034 "\t\tMiss (packets): %" PRIu64 "\n",
2035 table_info.name,
2036 stats.n_pkts_hit,
2037 stats.n_pkts_miss);
2038 out_size -= strlen(out);
2039 out += strlen(out);
2040
2041 for (j = 0; j < info.n_actions; j++) {
2042 struct rte_swx_ctl_action_info action_info;
2043
2044 status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
2045 if (status) {
2046 snprintf(out, out_size, "Action info get error.");
2047 return;
2048 }
2049
2050 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
2051 action_info.name,
2052 stats.n_pkts_action[j]);
2053 out_size -= strlen(out);
2054 out += strlen(out);
2055 }
2056 }
2057
2058 snprintf(out, out_size, "\nLearner tables:\n");
2059 out_size -= strlen(out);
2060 out += strlen(out);
2061
2062 for (i = 0; i < info.n_learners; i++) {
2063 struct rte_swx_ctl_learner_info learner_info;
2064 uint64_t n_pkts_action[info.n_actions];
2065 struct rte_swx_learner_stats stats = {
2066 .n_pkts_hit = 0,
2067 .n_pkts_miss = 0,
2068 .n_pkts_action = n_pkts_action,
2069 };
2070 uint32_t j;
2071
2072 status = rte_swx_ctl_learner_info_get(p->p, i, &learner_info);
2073 if (status) {
2074 snprintf(out, out_size, "Learner table info get error.");
2075 return;
2076 }
2077
2078 status = rte_swx_ctl_pipeline_learner_stats_read(p->p, learner_info.name, &stats);
2079 if (status) {
2080 snprintf(out, out_size, "Learner table stats read error.");
2081 return;
2082 }
2083
2084 snprintf(out, out_size, "\tLearner table %s:\n"
2085 "\t\tHit (packets): %" PRIu64 "\n"
2086 "\t\tMiss (packets): %" PRIu64 "\n"
2087 "\t\tLearn OK (packets): %" PRIu64 "\n"
2088 "\t\tLearn error (packets): %" PRIu64 "\n"
2089 "\t\tRearm (packets): %" PRIu64 "\n"
2090 "\t\tForget (packets): %" PRIu64 "\n",
2091 learner_info.name,
2092 stats.n_pkts_hit,
2093 stats.n_pkts_miss,
2094 stats.n_pkts_learn_ok,
2095 stats.n_pkts_learn_err,
2096 stats.n_pkts_rearm,
2097 stats.n_pkts_forget);
2098 out_size -= strlen(out);
2099 out += strlen(out);
2100
2101 for (j = 0; j < info.n_actions; j++) {
2102 struct rte_swx_ctl_action_info action_info;
2103
2104 status = rte_swx_ctl_action_info_get(p->p, j, &action_info);
2105 if (status) {
2106 snprintf(out, out_size, "Action info get error.");
2107 return;
2108 }
2109
2110 snprintf(out, out_size, "\t\tAction %s (packets): %" PRIu64 "\n",
2111 action_info.name,
2112 stats.n_pkts_action[j]);
2113 out_size -= strlen(out);
2114 out += strlen(out);
2115 }
2116 }
2117 }
2118
2119 /**
2120 * pipeline <pipeline_name> mirror session <session_id> port <port_id> clone fast | slow
2121 * truncate <truncation_length>
2122 */
2123 static void
cmd_softnic_pipeline_mirror_session(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)2124 cmd_softnic_pipeline_mirror_session(struct pmd_internals *softnic,
2125 char **tokens,
2126 uint32_t n_tokens,
2127 char *out,
2128 size_t out_size)
2129 {
2130 struct rte_swx_pipeline_mirroring_session_params params;
2131 struct pipeline *p;
2132 uint32_t session_id = 0;
2133 int status;
2134
2135 if (n_tokens != 11) {
2136 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2137 return;
2138 }
2139
2140 if (strcmp(tokens[0], "pipeline")) {
2141 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2142 return;
2143 }
2144
2145 p = softnic_pipeline_find(softnic, tokens[1]);
2146 if (!p) {
2147 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
2148 return;
2149 }
2150
2151 if (strcmp(tokens[2], "mirror")) {
2152 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mirror");
2153 return;
2154 }
2155
2156 if (strcmp(tokens[3], "session")) {
2157 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "session");
2158 return;
2159 }
2160
2161 if (parser_read_uint32(&session_id, tokens[4])) {
2162 snprintf(out, out_size, MSG_ARG_INVALID, "session_id");
2163 return;
2164 }
2165
2166 if (strcmp(tokens[5], "port")) {
2167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2168 return;
2169 }
2170
2171 if (parser_read_uint32(¶ms.port_id, tokens[6])) {
2172 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2173 return;
2174 }
2175
2176 if (strcmp(tokens[7], "clone")) {
2177 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "clone");
2178 return;
2179 }
2180
2181 if (!strcmp(tokens[8], "fast")) {
2182 params.fast_clone = 1;
2183 } else if (!strcmp(tokens[8], "slow")) {
2184 params.fast_clone = 0;
2185 } else {
2186 snprintf(out, out_size, MSG_ARG_INVALID, "clone");
2187 return;
2188 }
2189
2190 if (strcmp(tokens[9], "truncate")) {
2191 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "truncate");
2192 return;
2193 }
2194
2195 if (parser_read_uint32(¶ms.truncation_length, tokens[10])) {
2196 snprintf(out, out_size, MSG_ARG_INVALID, "truncation_length");
2197 return;
2198 }
2199
2200 status = rte_swx_ctl_pipeline_mirroring_session_set(p->p, session_id, ¶ms);
2201 if (status) {
2202 snprintf(out, out_size, "Command failed!\n");
2203 return;
2204 }
2205 }
2206
2207 /**
2208 * thread <thread_id> pipeline <pipeline_name> enable [ period <timer_period_ms> ]
2209 */
2210 static void
cmd_softnic_thread_pipeline_enable(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)2211 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
2212 char **tokens,
2213 uint32_t n_tokens,
2214 char *out,
2215 size_t out_size)
2216 {
2217 char *pipeline_name;
2218 struct pipeline *p;
2219 uint32_t thread_id;
2220 int status;
2221
2222 if (n_tokens != 5) {
2223 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2224 return;
2225 }
2226
2227 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
2228 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
2229 return;
2230 }
2231
2232 if (strcmp(tokens[2], "pipeline") != 0) {
2233 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2234 return;
2235 }
2236
2237 pipeline_name = tokens[3];
2238 p = softnic_pipeline_find(softnic, pipeline_name);
2239 if (!p) {
2240 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
2241 return;
2242 }
2243
2244 if (strcmp(tokens[4], "enable") != 0) {
2245 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
2246 return;
2247 }
2248
2249 status = softnic_thread_pipeline_enable(softnic, thread_id, p);
2250 if (status) {
2251 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
2252 return;
2253 }
2254 }
2255
2256 /**
2257 * thread <thread_id> pipeline <pipeline_name> disable
2258 */
2259 static void
cmd_softnic_thread_pipeline_disable(struct pmd_internals * softnic,char ** tokens,uint32_t n_tokens,char * out,size_t out_size)2260 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
2261 char **tokens,
2262 uint32_t n_tokens,
2263 char *out,
2264 size_t out_size)
2265 {
2266 char *pipeline_name;
2267 struct pipeline *p;
2268 uint32_t thread_id;
2269 int status;
2270
2271 if (n_tokens != 5) {
2272 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2273 return;
2274 }
2275
2276 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
2277 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
2278 return;
2279 }
2280
2281 if (strcmp(tokens[2], "pipeline") != 0) {
2282 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
2283 return;
2284 }
2285
2286 pipeline_name = tokens[3];
2287 p = softnic_pipeline_find(softnic, pipeline_name);
2288 if (!p) {
2289 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
2290 return;
2291 }
2292
2293 if (strcmp(tokens[4], "disable") != 0) {
2294 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2295 return;
2296 }
2297
2298 status = softnic_thread_pipeline_disable(softnic, thread_id, p);
2299 if (status) {
2300 snprintf(out, out_size, MSG_CMD_FAIL,
2301 "thread pipeline disable");
2302 return;
2303 }
2304 }
2305
2306 void
softnic_cli_process(char * in,char * out,size_t out_size,void * arg)2307 softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
2308 {
2309 char *tokens[CMD_MAX_TOKENS];
2310 uint32_t n_tokens = RTE_DIM(tokens);
2311 struct pmd_internals *softnic = arg;
2312 int status;
2313
2314 if (is_comment(in))
2315 return;
2316
2317 status = parse_tokenize_string(in, tokens, &n_tokens);
2318 if (status) {
2319 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
2320 return;
2321 }
2322
2323 if (n_tokens == 0)
2324 return;
2325
2326 if (strcmp(tokens[0], "mempool") == 0) {
2327 cmd_mempool(softnic, tokens, n_tokens, out, out_size);
2328 return;
2329 }
2330
2331 if (strcmp(tokens[0], "swq") == 0) {
2332 cmd_swq(softnic, tokens, n_tokens, out, out_size);
2333 return;
2334 }
2335
2336 if (!strcmp(tokens[0], "pipeline")) {
2337 if (n_tokens >= 2 && !strcmp(tokens[1], "codegen")) {
2338 cmd_softnic_pipeline_codegen(softnic, tokens, n_tokens, out, out_size);
2339 return;
2340 }
2341
2342 if (n_tokens >= 3 && !strcmp(tokens[1], "libbuild")) {
2343 cmd_softnic_pipeline_libbuild(softnic, tokens, n_tokens, out, out_size);
2344 return;
2345 }
2346
2347 if (n_tokens >= 3 && !strcmp(tokens[2], "build")) {
2348 cmd_softnic_pipeline_build(softnic, tokens, n_tokens, out, out_size);
2349 return;
2350 }
2351
2352 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "add")) {
2353 cmd_softnic_pipeline_table_add(softnic, tokens, n_tokens, out, out_size);
2354 return;
2355 }
2356
2357 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "delete")) {
2358 cmd_softnic_pipeline_table_delete(softnic, tokens, n_tokens,
2359 out, out_size);
2360 return;
2361 }
2362
2363 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "default")) {
2364 cmd_softnic_pipeline_table_default(softnic, tokens, n_tokens,
2365 out, out_size);
2366 return;
2367 }
2368
2369 if (n_tokens >= 5 && !strcmp(tokens[2], "table") && !strcmp(tokens[4], "show")) {
2370 cmd_softnic_pipeline_table_show(softnic, tokens, n_tokens, out, out_size);
2371 return;
2372 }
2373
2374 if (n_tokens >= 6 &&
2375 !strcmp(tokens[2], "selector") &&
2376 !strcmp(tokens[4], "group") &&
2377 !strcmp(tokens[5], "add")) {
2378 cmd_softnic_pipeline_selector_group_add(softnic, tokens, n_tokens,
2379 out, out_size);
2380 return;
2381 }
2382
2383 if (n_tokens >= 6 &&
2384 !strcmp(tokens[2], "selector") &&
2385 !strcmp(tokens[4], "group") &&
2386 !strcmp(tokens[5], "delete")) {
2387 cmd_softnic_pipeline_selector_group_delete(softnic, tokens, n_tokens,
2388 out, out_size);
2389 return;
2390 }
2391
2392 if (n_tokens >= 7 &&
2393 !strcmp(tokens[2], "selector") &&
2394 !strcmp(tokens[4], "group") &&
2395 !strcmp(tokens[5], "member") &&
2396 !strcmp(tokens[6], "add")) {
2397 cmd_softnic_pipeline_selector_group_member_add(softnic, tokens, n_tokens,
2398 out, out_size);
2399 return;
2400 }
2401
2402 if (n_tokens >= 7 &&
2403 !strcmp(tokens[2], "selector") &&
2404 !strcmp(tokens[4], "group") &&
2405 !strcmp(tokens[5], "member") &&
2406 !strcmp(tokens[6], "delete")) {
2407 cmd_softnic_pipeline_selector_group_member_delete(softnic, tokens, n_tokens,
2408 out, out_size);
2409 return;
2410 }
2411
2412 if (n_tokens >= 5 &&
2413 !strcmp(tokens[2], "selector") &&
2414 !strcmp(tokens[4], "show")) {
2415 cmd_softnic_pipeline_selector_show(softnic, tokens, n_tokens,
2416 out, out_size);
2417 return;
2418 }
2419
2420 if (n_tokens >= 5 &&
2421 !strcmp(tokens[2], "learner") &&
2422 !strcmp(tokens[4], "default")) {
2423 cmd_softnic_pipeline_learner_default(softnic, tokens, n_tokens,
2424 out, out_size);
2425 return;
2426 }
2427
2428 if (n_tokens >= 3 && !strcmp(tokens[2], "commit")) {
2429 cmd_softnic_pipeline_commit(softnic, tokens, n_tokens, out, out_size);
2430 return;
2431 }
2432
2433 if (n_tokens >= 3 && !strcmp(tokens[2], "abort")) {
2434 cmd_softnic_pipeline_abort(softnic, tokens, n_tokens, out, out_size);
2435 return;
2436 }
2437
2438 if (n_tokens >= 3 && !strcmp(tokens[2], "regrd")) {
2439 cmd_softnic_pipeline_regrd(softnic, tokens, n_tokens, out, out_size);
2440 return;
2441 }
2442
2443 if (n_tokens >= 3 && !strcmp(tokens[2], "regwr")) {
2444 cmd_softnic_pipeline_regwr(softnic, tokens, n_tokens, out, out_size);
2445 return;
2446 }
2447
2448 if (n_tokens >= 6 &&
2449 !strcmp(tokens[2], "meter") &&
2450 !strcmp(tokens[3], "profile") &&
2451 !strcmp(tokens[5], "add")) {
2452 cmd_softnic_pipeline_meter_profile_add(softnic, tokens, n_tokens,
2453 out, out_size);
2454 return;
2455 }
2456
2457 if (n_tokens >= 6 &&
2458 !strcmp(tokens[2], "meter") &&
2459 !strcmp(tokens[3], "profile") &&
2460 !strcmp(tokens[5], "delete")) {
2461 cmd_softnic_pipeline_meter_profile_delete(softnic, tokens, n_tokens,
2462 out, out_size);
2463 return;
2464 }
2465
2466 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "reset")) {
2467 cmd_softnic_pipeline_meter_reset(softnic, tokens, n_tokens, out, out_size);
2468 return;
2469 }
2470
2471 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "set")) {
2472 cmd_softnic_pipeline_meter_set(softnic, tokens, n_tokens, out, out_size);
2473 return;
2474 }
2475
2476 if (n_tokens >= 9 && !strcmp(tokens[2], "meter") && !strcmp(tokens[8], "stats")) {
2477 cmd_softnic_pipeline_meter_stats(softnic, tokens, n_tokens, out, out_size);
2478 return;
2479 }
2480
2481 if (n_tokens >= 3 && !strcmp(tokens[2], "stats")) {
2482 cmd_softnic_pipeline_stats(softnic, tokens, n_tokens, out, out_size);
2483 return;
2484 }
2485
2486 if (n_tokens >= 4 &&
2487 !strcmp(tokens[2], "mirror") &&
2488 !strcmp(tokens[3], "session")) {
2489 cmd_softnic_pipeline_mirror_session(softnic, tokens, n_tokens,
2490 out, out_size);
2491 return;
2492 }
2493 }
2494
2495 if (strcmp(tokens[0], "thread") == 0) {
2496 if (n_tokens >= 5 &&
2497 (strcmp(tokens[4], "enable") == 0)) {
2498 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens,
2499 out, out_size);
2500 return;
2501 }
2502
2503 if (n_tokens >= 5 &&
2504 (strcmp(tokens[4], "disable") == 0)) {
2505 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens,
2506 out, out_size);
2507 return;
2508 }
2509 }
2510
2511 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
2512 }
2513
2514 int
softnic_cli_script_process(struct pmd_internals * softnic,const char * file_name,size_t msg_in_len_max,size_t msg_out_len_max)2515 softnic_cli_script_process(struct pmd_internals *softnic,
2516 const char *file_name,
2517 size_t msg_in_len_max,
2518 size_t msg_out_len_max)
2519 {
2520 char *msg_in = NULL, *msg_out = NULL;
2521 FILE *f = NULL;
2522
2523 /* Check input arguments */
2524 if (file_name == NULL ||
2525 (strlen(file_name) == 0) ||
2526 msg_in_len_max == 0 ||
2527 msg_out_len_max == 0)
2528 return -EINVAL;
2529
2530 msg_in = malloc(msg_in_len_max + 1);
2531 msg_out = malloc(msg_out_len_max + 1);
2532 if (msg_in == NULL ||
2533 msg_out == NULL) {
2534 free(msg_out);
2535 free(msg_in);
2536 return -ENOMEM;
2537 }
2538
2539 /* Open input file */
2540 f = fopen(file_name, "r");
2541 if (f == NULL) {
2542 free(msg_out);
2543 free(msg_in);
2544 return -EIO;
2545 }
2546
2547 /* Read file */
2548 for ( ; ; ) {
2549 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
2550 break;
2551
2552 printf("%s", msg_in);
2553 msg_out[0] = 0;
2554
2555 softnic_cli_process(msg_in,
2556 msg_out,
2557 msg_out_len_max,
2558 softnic);
2559
2560 if (strlen(msg_out))
2561 printf("%s", msg_out);
2562 }
2563
2564 /* Close file */
2565 fclose(f);
2566 free(msg_out);
2567 free(msg_in);
2568 return 0;
2569 }
2570