1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2020 Intel Corporation
10 #include <rte_common.h>
11 #include <rte_ethdev.h>
12 #include <rte_swx_port_ethdev.h>
13 #include <rte_swx_port_ring.h>
14 #include <rte_swx_port_source_sink.h>
15 #include <rte_swx_port_fd.h>
16 #include <rte_swx_pipeline.h>
17 #include <rte_swx_ctl.h>
24 #ifndef CMD_MAX_TOKENS
25 #define CMD_MAX_TOKENS 256
28 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
29 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
30 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
31 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
32 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
33 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
34 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
35 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
36 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
37 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
38 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
40 #define skip_white_spaces(pos) \
42 __typeof__(pos) _p = (pos); \
43 for ( ; isspace(*_p); _p++) \
49 parser_read_uint64(uint64_t *value, const char *p)
54 p = skip_white_spaces(p);
58 val = strtoul(p, &next, 0);
80 p = skip_white_spaces(p);
89 parser_read_uint32(uint32_t *value, const char *p)
92 int ret = parser_read_uint64(&val, p);
105 parser_read_uint16(uint16_t *value, const char *p)
108 int ret = parser_read_uint64(&val, p);
113 if (val > UINT16_MAX)
120 #define PARSE_DELIMITER " \f\n\r\t\v"
123 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
127 if ((string == NULL) ||
132 for (i = 0; i < *n_tokens; i++) {
133 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
134 if (tokens[i] == NULL)
138 if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string))
148 if ((strlen(in) && index("!#%;", in[0])) ||
149 (strncmp(in, "//", 2) == 0) ||
150 (strncmp(in, "--", 2) == 0))
156 static const char cmd_mempool_help[] =
157 "mempool <mempool_name>\n"
158 " buffer <buffer_size>\n"
159 " pool <pool_size>\n"
160 " cache <cache_size>\n"
164 cmd_mempool(char **tokens,
170 struct mempool_params p;
172 struct mempool *mempool;
174 if (n_tokens != 10) {
175 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
181 if (strcmp(tokens[2], "buffer") != 0) {
182 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
186 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
187 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
191 if (strcmp(tokens[4], "pool") != 0) {
192 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
196 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
197 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
201 if (strcmp(tokens[6], "cache") != 0) {
202 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
206 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
207 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
211 if (strcmp(tokens[8], "cpu") != 0) {
212 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
216 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
217 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
221 mempool = mempool_create(obj, name, &p);
222 if (mempool == NULL) {
223 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
228 static const char cmd_link_help[] =
230 " dev <device_name> | port <port_id>\n"
231 " rxq <n_queues> <queue_size> <mempool_name>\n"
232 " txq <n_queues> <queue_size>\n"
233 " promiscuous on | off\n"
234 " [rss <qid_0> ... <qid_n>]\n";
237 cmd_link(char **tokens,
243 struct link_params p;
244 struct link_params_rss rss;
248 memset(&p, 0, sizeof(p));
250 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
251 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
256 if (strcmp(tokens[2], "dev") == 0)
257 p.dev_name = tokens[3];
258 else if (strcmp(tokens[2], "port") == 0) {
261 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
262 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
266 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
270 if (strcmp(tokens[4], "rxq") != 0) {
271 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
275 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
276 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
279 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
280 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
284 p.rx.mempool_name = tokens[7];
286 if (strcmp(tokens[8], "txq") != 0) {
287 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
291 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
292 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
296 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
297 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
301 if (strcmp(tokens[11], "promiscuous") != 0) {
302 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
306 if (strcmp(tokens[12], "on") == 0)
308 else if (strcmp(tokens[12], "off") == 0)
311 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
318 uint32_t queue_id, i;
320 if (strcmp(tokens[13], "rss") != 0) {
321 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
328 for (i = 14; i < n_tokens; i++) {
329 if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
330 snprintf(out, out_size, MSG_ARG_INVALID,
335 rss.queue_id[rss.n_queues] = queue_id;
340 link = link_create(obj, name, &p);
342 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
347 /* Print the link stats and info */
349 print_link_info(struct link *link, char *out, size_t out_size)
351 struct rte_eth_stats stats;
352 struct rte_ether_addr mac_addr;
353 struct rte_eth_link eth_link;
357 memset(&stats, 0, sizeof(stats));
358 rte_eth_stats_get(link->port_id, &stats);
360 ret = rte_eth_macaddr_get(link->port_id, &mac_addr);
362 snprintf(out, out_size, "\n%s: MAC address get failed: %s",
363 link->name, rte_strerror(-ret));
367 ret = rte_eth_link_get(link->port_id, ð_link);
369 snprintf(out, out_size, "\n%s: link get failed: %s",
370 link->name, rte_strerror(-ret));
374 rte_eth_dev_get_mtu(link->port_id, &mtu);
376 snprintf(out, out_size,
378 "%s: flags=<%s> mtu %u\n"
379 "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n"
380 "\tport# %u speed %s\n"
381 "\tRX packets %" PRIu64" bytes %" PRIu64"\n"
382 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
383 "\tTX packets %" PRIu64" bytes %" PRIu64"\n"
384 "\tTX errors %" PRIu64"\n",
386 eth_link.link_status == 0 ? "DOWN" : "UP",
388 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
389 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
390 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5],
394 rte_eth_link_speed_to_str(eth_link.link_speed),
406 * link show [<link_name>]
409 cmd_link_show(char **tokens,
418 if (n_tokens != 2 && n_tokens != 3) {
419 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
424 link = link_next(obj, NULL);
426 while (link != NULL) {
427 out_size = out_size - strlen(out);
428 out = &out[strlen(out)];
430 print_link_info(link, out, out_size);
431 link = link_next(obj, link);
434 out_size = out_size - strlen(out);
435 out = &out[strlen(out)];
437 link_name = tokens[2];
438 link = link_find(obj, link_name);
441 snprintf(out, out_size, MSG_ARG_INVALID,
442 "Link does not exist");
445 print_link_info(link, out, out_size);
449 static const char cmd_ring_help[] =
450 "ring <ring_name> size <size> numa <numa_node>\n";
453 cmd_ring(char **tokens,
459 struct ring_params p;
464 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
470 if (strcmp(tokens[2], "size") != 0) {
471 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
475 if (parser_read_uint32(&p.size, tokens[3]) != 0) {
476 snprintf(out, out_size, MSG_ARG_INVALID, "size");
480 if (strcmp(tokens[4], "numa") != 0) {
481 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
485 if (parser_read_uint32(&p.numa_node, tokens[5]) != 0) {
486 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
490 ring = ring_create(obj, name, &p);
492 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
497 static const char cmd_tap_help[] =
501 cmd_tap(char **tokens,
511 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
516 tap = tap_create(obj, name);
518 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
523 static const char cmd_pipeline_create_help[] =
524 "pipeline <pipeline_name> create <numa_node>\n";
527 cmd_pipeline_create(char **tokens,
538 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
544 if (parser_read_uint32(&numa_node, tokens[3]) != 0) {
545 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
549 p = pipeline_create(obj, name, (int)numa_node);
551 snprintf(out, out_size, "pipeline create error.");
556 static const char cmd_pipeline_port_in_help[] =
557 "pipeline <pipeline_name> port in <port_id>\n"
558 " link <link_name> rxq <queue_id> bsz <burst_size>\n"
559 " ring <ring_name> bsz <burst_size>\n"
560 " | source <mempool_name> <file_name>\n"
561 " | tap <tap_name> mempool <mempool_name> mtu <mtu> bsz <burst_size>\n";
564 cmd_pipeline_port_in(char **tokens,
572 uint32_t port_id = 0, t0;
575 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
579 p = pipeline_find(obj, tokens[1]);
581 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
585 if (strcmp(tokens[2], "port") != 0) {
586 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
590 if (strcmp(tokens[3], "in") != 0) {
591 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
595 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
596 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
602 if (strcmp(tokens[t0], "link") == 0) {
603 struct rte_swx_port_ethdev_reader_params params;
606 if (n_tokens < t0 + 6) {
607 snprintf(out, out_size, MSG_ARG_MISMATCH,
608 "pipeline port in link");
612 link = link_find(obj, tokens[t0 + 1]);
614 snprintf(out, out_size, MSG_ARG_INVALID,
618 params.dev_name = link->dev_name;
620 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
621 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
625 if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
626 snprintf(out, out_size, MSG_ARG_INVALID,
631 if (strcmp(tokens[t0 + 4], "bsz") != 0) {
632 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
636 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
637 snprintf(out, out_size, MSG_ARG_INVALID,
644 status = rte_swx_pipeline_port_in_config(p->p,
648 } else if (strcmp(tokens[t0], "ring") == 0) {
649 struct rte_swx_port_ring_reader_params params;
652 if (n_tokens < t0 + 4) {
653 snprintf(out, out_size, MSG_ARG_MISMATCH,
654 "pipeline port in ring");
658 ring = ring_find(obj, tokens[t0 + 1]);
660 snprintf(out, out_size, MSG_ARG_INVALID,
664 params.name = ring->name;
666 if (strcmp(tokens[t0 + 2], "bsz") != 0) {
667 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
671 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
672 snprintf(out, out_size, MSG_ARG_INVALID,
679 status = rte_swx_pipeline_port_in_config(p->p,
683 } else if (strcmp(tokens[t0], "source") == 0) {
684 struct rte_swx_port_source_params params;
687 if (n_tokens < t0 + 3) {
688 snprintf(out, out_size, MSG_ARG_MISMATCH,
689 "pipeline port in source");
693 mp = mempool_find(obj, tokens[t0 + 1]);
695 snprintf(out, out_size, MSG_ARG_INVALID,
701 params.file_name = tokens[t0 + 2];
705 status = rte_swx_pipeline_port_in_config(p->p,
709 } else if (strcmp(tokens[t0], "tap") == 0) {
710 struct rte_swx_port_fd_reader_params params;
714 if (n_tokens < t0 + 8) {
715 snprintf(out, out_size, MSG_ARG_MISMATCH,
716 "pipeline port in tap");
720 tap = tap_find(obj, tokens[t0 + 1]);
722 snprintf(out, out_size, MSG_ARG_INVALID,
728 if (strcmp(tokens[t0 + 2], "mempool") != 0) {
729 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
734 mp = mempool_find(obj, tokens[t0 + 3]);
736 snprintf(out, out_size, MSG_ARG_INVALID,
740 params.mempool = mp->m;
742 if (strcmp(tokens[t0 + 4], "mtu") != 0) {
743 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
748 if (parser_read_uint32(¶ms.mtu, tokens[t0 + 5]) != 0) {
749 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
753 if (strcmp(tokens[t0 + 6], "bsz") != 0) {
754 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
758 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 7])) {
759 snprintf(out, out_size, MSG_ARG_INVALID,
766 status = rte_swx_pipeline_port_in_config(p->p,
772 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
777 snprintf(out, out_size, "port in error.");
781 if (n_tokens != t0) {
782 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
787 static const char cmd_pipeline_port_out_help[] =
788 "pipeline <pipeline_name> port out <port_id>\n"
789 " link <link_name> txq <txq_id> bsz <burst_size>\n"
790 " ring <ring_name> bsz <burst_size>\n"
791 " | sink <file_name> | none\n"
792 " | tap <tap_name> bsz <burst_size>\n";
795 cmd_pipeline_port_out(char **tokens,
803 uint32_t port_id = 0, t0;
806 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
810 p = pipeline_find(obj, tokens[1]);
812 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
816 if (strcmp(tokens[2], "port") != 0) {
817 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
821 if (strcmp(tokens[3], "out") != 0) {
822 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
826 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
827 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
833 if (strcmp(tokens[t0], "link") == 0) {
834 struct rte_swx_port_ethdev_writer_params params;
837 if (n_tokens < t0 + 6) {
838 snprintf(out, out_size, MSG_ARG_MISMATCH,
839 "pipeline port out link");
843 link = link_find(obj, tokens[t0 + 1]);
845 snprintf(out, out_size, MSG_ARG_INVALID,
849 params.dev_name = link->dev_name;
851 if (strcmp(tokens[t0 + 2], "txq") != 0) {
852 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
856 if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
857 snprintf(out, out_size, MSG_ARG_INVALID,
862 if (strcmp(tokens[t0 + 4], "bsz") != 0) {
863 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
867 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
868 snprintf(out, out_size, MSG_ARG_INVALID,
875 status = rte_swx_pipeline_port_out_config(p->p,
879 } else if (strcmp(tokens[t0], "ring") == 0) {
880 struct rte_swx_port_ring_writer_params params;
883 if (n_tokens < t0 + 4) {
884 snprintf(out, out_size, MSG_ARG_MISMATCH,
885 "pipeline port out link");
889 ring = ring_find(obj, tokens[t0 + 1]);
891 snprintf(out, out_size, MSG_ARG_INVALID,
895 params.name = ring->name;
897 if (strcmp(tokens[t0 + 2], "bsz") != 0) {
898 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
902 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
903 snprintf(out, out_size, MSG_ARG_INVALID,
910 status = rte_swx_pipeline_port_out_config(p->p,
914 } else if (strcmp(tokens[t0], "sink") == 0) {
915 struct rte_swx_port_sink_params params;
917 params.file_name = strcmp(tokens[t0 + 1], "none") ?
918 tokens[t0 + 1] : NULL;
922 status = rte_swx_pipeline_port_out_config(p->p,
926 } else if (strcmp(tokens[t0], "tap") == 0) {
927 struct rte_swx_port_fd_writer_params params;
930 if (n_tokens < t0 + 4) {
931 snprintf(out, out_size, MSG_ARG_MISMATCH,
932 "pipeline port out tap");
936 tap = tap_find(obj, tokens[t0 + 1]);
938 snprintf(out, out_size, MSG_ARG_INVALID,
944 if (strcmp(tokens[t0 + 2], "bsz") != 0) {
945 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
949 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
950 snprintf(out, out_size, MSG_ARG_INVALID,
957 status = rte_swx_pipeline_port_out_config(p->p,
962 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
967 snprintf(out, out_size, "port out error.");
971 if (n_tokens != t0) {
972 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
977 static const char cmd_pipeline_build_help[] =
978 "pipeline <pipeline_name> build <spec_file>\n";
981 cmd_pipeline_build(char **tokens,
987 struct pipeline *p = NULL;
994 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
998 p = pipeline_find(obj, tokens[1]);
1000 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1004 spec = fopen(tokens[3], "r");
1006 snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
1010 status = rte_swx_pipeline_build_from_spec(p->p,
1016 snprintf(out, out_size, "Error %d at line %u: %s\n.",
1017 status, err_line, err_msg);
1021 p->ctl = rte_swx_ctl_pipeline_create(p->p);
1023 snprintf(out, out_size, "Pipeline control create failed.");
1024 rte_swx_pipeline_free(p->p);
1030 table_entry_free(struct rte_swx_table_entry *entry)
1036 free(entry->key_mask);
1037 free(entry->action_data);
1041 static const char cmd_pipeline_table_update_help[] =
1042 "pipeline <pipeline_name> table <table_name> update <file_name_add> "
1043 "<file_name_delete> <file_name_default>";
1046 cmd_pipeline_table_update(char **tokens,
1053 char *pipeline_name, *table_name, *line = NULL;
1054 char *file_name_add, *file_name_delete, *file_name_default;
1055 FILE *file_add = NULL, *file_delete = NULL, *file_default = NULL;
1059 if (n_tokens != 8) {
1060 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1064 pipeline_name = tokens[1];
1065 p = pipeline_find(obj, pipeline_name);
1066 if (!p || !p->ctl) {
1067 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1071 if (strcmp(tokens[2], "table") != 0) {
1072 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1076 table_name = tokens[3];
1078 if (strcmp(tokens[4], "update") != 0) {
1079 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "update");
1083 file_name_add = tokens[5];
1084 file_name_delete = tokens[6];
1085 file_name_default = tokens[7];
1088 if (strcmp(file_name_add, "none")) {
1089 file_add = fopen(file_name_add, "r");
1091 snprintf(out, out_size, "Cannot open file %s",
1097 if (strcmp(file_name_delete, "none")) {
1098 file_delete = fopen(file_name_delete, "r");
1100 snprintf(out, out_size, "Cannot open file %s",
1106 if (strcmp(file_name_default, "none")) {
1107 file_default = fopen(file_name_default, "r");
1108 if (!file_default) {
1109 snprintf(out, out_size, "Cannot open file %s",
1115 if (!file_add && !file_delete && !file_default) {
1116 snprintf(out, out_size, "Nothing to be done.");
1120 /* Buffer allocation. */
1121 line = malloc(2048);
1123 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
1129 for (line_id = 1; ; line_id++) {
1130 struct rte_swx_table_entry *entry;
1131 int is_blank_or_comment;
1133 if (fgets(line, 2048, file_add) == NULL)
1136 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1139 &is_blank_or_comment);
1141 if (is_blank_or_comment)
1144 snprintf(out, out_size, MSG_FILE_ERR,
1145 file_name_add, line_id);
1149 status = rte_swx_ctl_pipeline_table_entry_add(p->ctl,
1152 table_entry_free(entry);
1154 snprintf(out, out_size,
1155 "Invalid entry in file %s at line %u",
1156 file_name_add, line_id);
1164 for (line_id = 1; ; line_id++) {
1165 struct rte_swx_table_entry *entry;
1166 int is_blank_or_comment;
1168 if (fgets(line, 2048, file_delete) == NULL)
1171 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1174 &is_blank_or_comment);
1176 if (is_blank_or_comment)
1179 snprintf(out, out_size, MSG_FILE_ERR,
1180 file_name_delete, line_id);
1184 status = rte_swx_ctl_pipeline_table_entry_delete(p->ctl,
1187 table_entry_free(entry);
1189 snprintf(out, out_size,
1190 "Invalid entry in file %s at line %u",
1191 file_name_delete, line_id);
1198 for (line_id = 1; ; line_id++) {
1199 struct rte_swx_table_entry *entry;
1200 int is_blank_or_comment;
1202 if (fgets(line, 2048, file_default) == NULL)
1205 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1208 &is_blank_or_comment);
1210 if (is_blank_or_comment)
1213 snprintf(out, out_size, MSG_FILE_ERR,
1214 file_name_default, line_id);
1218 status = rte_swx_ctl_pipeline_table_default_entry_add(p->ctl,
1221 table_entry_free(entry);
1223 snprintf(out, out_size,
1224 "Invalid entry in file %s at line %u",
1225 file_name_default, line_id);
1230 status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
1232 snprintf(out, out_size, "Commit failed.");
1237 rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name);
1243 fclose(file_delete);
1245 fclose(file_default);
1249 rte_swx_ctl_pipeline_abort(p->ctl);
1254 fclose(file_delete);
1256 fclose(file_default);
1259 static const char cmd_pipeline_regrd_help[] =
1260 "pipeline <pipeline_name> regrd <register_array_name> <index>\n";
1263 cmd_pipeline_regrd(char **tokens,
1275 if (n_tokens != 5) {
1276 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1280 p = pipeline_find(obj, tokens[1]);
1281 if (!p || !p->ctl) {
1282 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1286 if (strcmp(tokens[2], "regrd")) {
1287 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regrd");
1293 if (parser_read_uint32(&idx, tokens[4])) {
1294 snprintf(out, out_size, MSG_ARG_INVALID, "index");
1298 status = rte_swx_ctl_pipeline_regarray_read(p->p, name, idx, &value);
1300 snprintf(out, out_size, "Command failed.\n");
1304 snprintf(out, out_size, "0x%" PRIx64 "\n", value);
1307 static const char cmd_pipeline_regwr_help[] =
1308 "pipeline <pipeline_name> regwr <register_array_name> <index> <value>\n";
1311 cmd_pipeline_regwr(char **tokens,
1323 if (n_tokens != 6) {
1324 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1328 p = pipeline_find(obj, tokens[1]);
1329 if (!p || !p->ctl) {
1330 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1334 if (strcmp(tokens[2], "regwr")) {
1335 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "regwr");
1341 if (parser_read_uint32(&idx, tokens[4])) {
1342 snprintf(out, out_size, MSG_ARG_INVALID, "index");
1346 if (parser_read_uint64(&value, tokens[5])) {
1347 snprintf(out, out_size, MSG_ARG_INVALID, "value");
1351 status = rte_swx_ctl_pipeline_regarray_write(p->p, name, idx, value);
1353 snprintf(out, out_size, "Command failed.\n");
1358 static const char cmd_pipeline_stats_help[] =
1359 "pipeline <pipeline_name> stats\n";
1362 cmd_pipeline_stats(char **tokens,
1368 struct rte_swx_ctl_pipeline_info info;
1373 if (n_tokens != 3) {
1374 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1378 p = pipeline_find(obj, tokens[1]);
1379 if (!p || !p->ctl) {
1380 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1384 if (strcmp(tokens[2], "stats")) {
1385 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1389 status = rte_swx_ctl_pipeline_info_get(p->p, &info);
1391 snprintf(out, out_size, "Pipeline info get error.");
1395 snprintf(out, out_size, "Input ports:\n");
1396 out_size -= strlen(out);
1399 for (i = 0; i < info.n_ports_in; i++) {
1400 struct rte_swx_port_in_stats stats;
1402 rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
1404 snprintf(out, out_size, "\tPort %u:"
1407 " empty %" PRIu64 "\n",
1408 i, stats.n_pkts, stats.n_bytes, stats.n_empty);
1409 out_size -= strlen(out);
1413 snprintf(out, out_size, "Output ports:\n");
1414 out_size -= strlen(out);
1417 for (i = 0; i < info.n_ports_out; i++) {
1418 struct rte_swx_port_out_stats stats;
1420 rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
1422 snprintf(out, out_size, "\tPort %u:"
1424 " bytes %" PRIu64 "\n",
1425 i, stats.n_pkts, stats.n_bytes);
1426 out_size -= strlen(out);
1431 static const char cmd_thread_pipeline_enable_help[] =
1432 "thread <thread_id> pipeline <pipeline_name> enable\n";
1435 cmd_thread_pipeline_enable(char **tokens,
1441 char *pipeline_name;
1446 if (n_tokens != 5) {
1447 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1451 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1452 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1456 if (strcmp(tokens[2], "pipeline") != 0) {
1457 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1461 pipeline_name = tokens[3];
1462 p = pipeline_find(obj, pipeline_name);
1463 if (!p || !p->ctl) {
1464 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1468 if (strcmp(tokens[4], "enable") != 0) {
1469 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1473 status = thread_pipeline_enable(thread_id, obj, pipeline_name);
1475 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
1480 static const char cmd_thread_pipeline_disable_help[] =
1481 "thread <thread_id> pipeline <pipeline_name> disable\n";
1484 cmd_thread_pipeline_disable(char **tokens,
1491 char *pipeline_name;
1495 if (n_tokens != 5) {
1496 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1500 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1501 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1505 if (strcmp(tokens[2], "pipeline") != 0) {
1506 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1510 pipeline_name = tokens[3];
1511 p = pipeline_find(obj, pipeline_name);
1512 if (!p || !p->ctl) {
1513 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1517 if (strcmp(tokens[4], "disable") != 0) {
1518 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
1522 status = thread_pipeline_disable(thread_id, obj, pipeline_name);
1524 snprintf(out, out_size, MSG_CMD_FAIL,
1525 "thread pipeline disable");
1531 cmd_help(char **tokens,
1535 void *arg __rte_unused)
1540 if (n_tokens == 0) {
1541 snprintf(out, out_size,
1542 "Type 'help <command>' for command details.\n\n"
1543 "List of commands:\n"
1547 "\tpipeline create\n"
1548 "\tpipeline port in\n"
1549 "\tpipeline port out\n"
1550 "\tpipeline build\n"
1551 "\tpipeline table update\n"
1552 "\tpipeline regrd\n"
1553 "\tpipeline regwr\n"
1554 "\tpipeline stats\n"
1555 "\tthread pipeline enable\n"
1556 "\tthread pipeline disable\n\n");
1560 if (strcmp(tokens[0], "mempool") == 0) {
1561 snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
1565 if (strcmp(tokens[0], "link") == 0) {
1566 snprintf(out, out_size, "\n%s\n", cmd_link_help);
1570 if (strcmp(tokens[0], "ring") == 0) {
1571 snprintf(out, out_size, "\n%s\n", cmd_ring_help);
1575 if (strcmp(tokens[0], "tap") == 0) {
1576 snprintf(out, out_size, "\n%s\n", cmd_tap_help);
1580 if ((strcmp(tokens[0], "pipeline") == 0) &&
1581 (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) {
1582 snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
1586 if ((strcmp(tokens[0], "pipeline") == 0) &&
1587 (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
1588 if (strcmp(tokens[2], "in") == 0) {
1589 snprintf(out, out_size, "\n%s\n",
1590 cmd_pipeline_port_in_help);
1594 if (strcmp(tokens[2], "out") == 0) {
1595 snprintf(out, out_size, "\n%s\n",
1596 cmd_pipeline_port_out_help);
1601 if ((strcmp(tokens[0], "pipeline") == 0) &&
1602 (n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
1603 snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
1607 if ((strcmp(tokens[0], "pipeline") == 0) &&
1609 (strcmp(tokens[1], "table") == 0) &&
1610 (strcmp(tokens[2], "update") == 0)) {
1611 snprintf(out, out_size, "\n%s\n",
1612 cmd_pipeline_table_update_help);
1616 if ((strcmp(tokens[0], "pipeline") == 0) &&
1617 (n_tokens == 2) && (strcmp(tokens[1], "regrd") == 0)) {
1618 snprintf(out, out_size, "\n%s\n", cmd_pipeline_regrd_help);
1622 if ((strcmp(tokens[0], "pipeline") == 0) &&
1623 (n_tokens == 2) && (strcmp(tokens[1], "regwr") == 0)) {
1624 snprintf(out, out_size, "\n%s\n", cmd_pipeline_regwr_help);
1628 if ((strcmp(tokens[0], "pipeline") == 0) &&
1629 (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
1630 snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
1634 if ((n_tokens == 3) &&
1635 (strcmp(tokens[0], "thread") == 0) &&
1636 (strcmp(tokens[1], "pipeline") == 0)) {
1637 if (strcmp(tokens[2], "enable") == 0) {
1638 snprintf(out, out_size, "\n%s\n",
1639 cmd_thread_pipeline_enable_help);
1643 if (strcmp(tokens[2], "disable") == 0) {
1644 snprintf(out, out_size, "\n%s\n",
1645 cmd_thread_pipeline_disable_help);
1650 snprintf(out, out_size, "Invalid command\n");
1654 cli_process(char *in, char *out, size_t out_size, void *obj)
1656 char *tokens[CMD_MAX_TOKENS];
1657 uint32_t n_tokens = RTE_DIM(tokens);
1663 status = parse_tokenize_string(in, tokens, &n_tokens);
1665 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
1672 if (strcmp(tokens[0], "help") == 0) {
1673 cmd_help(tokens, n_tokens, out, out_size, obj);
1677 if (strcmp(tokens[0], "mempool") == 0) {
1678 cmd_mempool(tokens, n_tokens, out, out_size, obj);
1682 if (strcmp(tokens[0], "link") == 0) {
1683 if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
1684 cmd_link_show(tokens, n_tokens, out, out_size, obj);
1688 cmd_link(tokens, n_tokens, out, out_size, obj);
1692 if (strcmp(tokens[0], "ring") == 0) {
1693 cmd_ring(tokens, n_tokens, out, out_size, obj);
1697 if (strcmp(tokens[0], "tap") == 0) {
1698 cmd_tap(tokens, n_tokens, out, out_size, obj);
1702 if (strcmp(tokens[0], "pipeline") == 0) {
1703 if ((n_tokens >= 3) &&
1704 (strcmp(tokens[2], "create") == 0)) {
1705 cmd_pipeline_create(tokens, n_tokens, out, out_size,
1710 if ((n_tokens >= 4) &&
1711 (strcmp(tokens[2], "port") == 0) &&
1712 (strcmp(tokens[3], "in") == 0)) {
1713 cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
1718 if ((n_tokens >= 4) &&
1719 (strcmp(tokens[2], "port") == 0) &&
1720 (strcmp(tokens[3], "out") == 0)) {
1721 cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
1726 if ((n_tokens >= 3) &&
1727 (strcmp(tokens[2], "build") == 0)) {
1728 cmd_pipeline_build(tokens, n_tokens, out, out_size,
1733 if ((n_tokens >= 3) &&
1734 (strcmp(tokens[2], "table") == 0)) {
1735 cmd_pipeline_table_update(tokens, n_tokens, out,
1740 if ((n_tokens >= 3) &&
1741 (strcmp(tokens[2], "regrd") == 0)) {
1742 cmd_pipeline_regrd(tokens, n_tokens, out, out_size, obj);
1746 if ((n_tokens >= 3) &&
1747 (strcmp(tokens[2], "regwr") == 0)) {
1748 cmd_pipeline_regwr(tokens, n_tokens, out, out_size, obj);
1752 if ((n_tokens >= 3) &&
1753 (strcmp(tokens[2], "stats") == 0)) {
1754 cmd_pipeline_stats(tokens, n_tokens, out, out_size,
1760 if (strcmp(tokens[0], "thread") == 0) {
1761 if ((n_tokens >= 5) &&
1762 (strcmp(tokens[4], "enable") == 0)) {
1763 cmd_thread_pipeline_enable(tokens, n_tokens,
1764 out, out_size, obj);
1768 if ((n_tokens >= 5) &&
1769 (strcmp(tokens[4], "disable") == 0)) {
1770 cmd_thread_pipeline_disable(tokens, n_tokens,
1771 out, out_size, obj);
1776 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
1780 cli_script_process(const char *file_name,
1781 size_t msg_in_len_max,
1782 size_t msg_out_len_max,
1785 char *msg_in = NULL, *msg_out = NULL;
1788 /* Check input arguments */
1789 if ((file_name == NULL) ||
1790 (strlen(file_name) == 0) ||
1791 (msg_in_len_max == 0) ||
1792 (msg_out_len_max == 0))
1795 msg_in = malloc(msg_in_len_max + 1);
1796 msg_out = malloc(msg_out_len_max + 1);
1797 if ((msg_in == NULL) ||
1798 (msg_out == NULL)) {
1804 /* Open input file */
1805 f = fopen(file_name, "r");
1814 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
1817 printf("%s", msg_in);
1825 if (strlen(msg_out))
1826 printf("%s", msg_out);