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, 10);
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_stats_help[] =
1260 "pipeline <pipeline_name> stats\n";
1263 cmd_pipeline_stats(char **tokens,
1269 struct rte_swx_ctl_pipeline_info info;
1274 if (n_tokens != 3) {
1275 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1279 p = pipeline_find(obj, tokens[1]);
1280 if (!p || !p->ctl) {
1281 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1285 if (strcmp(tokens[2], "stats")) {
1286 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1290 status = rte_swx_ctl_pipeline_info_get(p->p, &info);
1292 snprintf(out, out_size, "Pipeline info get error.");
1296 snprintf(out, out_size, "Input ports:\n");
1297 out_size -= strlen(out);
1300 for (i = 0; i < info.n_ports_in; i++) {
1301 struct rte_swx_port_in_stats stats;
1303 rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
1305 snprintf(out, out_size, "\tPort %u:"
1308 " empty %" PRIu64 "\n",
1309 i, stats.n_pkts, stats.n_bytes, stats.n_empty);
1310 out_size -= strlen(out);
1314 snprintf(out, out_size, "Output ports:\n");
1315 out_size -= strlen(out);
1318 for (i = 0; i < info.n_ports_out; i++) {
1319 struct rte_swx_port_out_stats stats;
1321 rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
1323 snprintf(out, out_size, "\tPort %u:"
1325 " bytes %" PRIu64 "\n",
1326 i, stats.n_pkts, stats.n_bytes);
1327 out_size -= strlen(out);
1332 static const char cmd_thread_pipeline_enable_help[] =
1333 "thread <thread_id> pipeline <pipeline_name> enable\n";
1336 cmd_thread_pipeline_enable(char **tokens,
1342 char *pipeline_name;
1347 if (n_tokens != 5) {
1348 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1352 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1353 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1357 if (strcmp(tokens[2], "pipeline") != 0) {
1358 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1362 pipeline_name = tokens[3];
1363 p = pipeline_find(obj, pipeline_name);
1364 if (!p || !p->ctl) {
1365 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1369 if (strcmp(tokens[4], "enable") != 0) {
1370 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1374 status = thread_pipeline_enable(thread_id, obj, pipeline_name);
1376 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
1381 static const char cmd_thread_pipeline_disable_help[] =
1382 "thread <thread_id> pipeline <pipeline_name> disable\n";
1385 cmd_thread_pipeline_disable(char **tokens,
1392 char *pipeline_name;
1396 if (n_tokens != 5) {
1397 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1401 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1402 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1406 if (strcmp(tokens[2], "pipeline") != 0) {
1407 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1411 pipeline_name = tokens[3];
1412 p = pipeline_find(obj, pipeline_name);
1413 if (!p || !p->ctl) {
1414 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1418 if (strcmp(tokens[4], "disable") != 0) {
1419 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
1423 status = thread_pipeline_disable(thread_id, obj, pipeline_name);
1425 snprintf(out, out_size, MSG_CMD_FAIL,
1426 "thread pipeline disable");
1432 cmd_help(char **tokens,
1436 void *arg __rte_unused)
1441 if (n_tokens == 0) {
1442 snprintf(out, out_size,
1443 "Type 'help <command>' for command details.\n\n"
1444 "List of commands:\n"
1448 "\tpipeline create\n"
1449 "\tpipeline port in\n"
1450 "\tpipeline port out\n"
1451 "\tpipeline build\n"
1452 "\tpipeline table update\n"
1453 "\tpipeline stats\n"
1454 "\tthread pipeline enable\n"
1455 "\tthread pipeline disable\n\n");
1459 if (strcmp(tokens[0], "mempool") == 0) {
1460 snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
1464 if (strcmp(tokens[0], "link") == 0) {
1465 snprintf(out, out_size, "\n%s\n", cmd_link_help);
1469 if (strcmp(tokens[0], "ring") == 0) {
1470 snprintf(out, out_size, "\n%s\n", cmd_ring_help);
1474 if (strcmp(tokens[0], "tap") == 0) {
1475 snprintf(out, out_size, "\n%s\n", cmd_tap_help);
1479 if ((strcmp(tokens[0], "pipeline") == 0) &&
1480 (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) {
1481 snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
1485 if ((strcmp(tokens[0], "pipeline") == 0) &&
1486 (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
1487 if (strcmp(tokens[2], "in") == 0) {
1488 snprintf(out, out_size, "\n%s\n",
1489 cmd_pipeline_port_in_help);
1493 if (strcmp(tokens[2], "out") == 0) {
1494 snprintf(out, out_size, "\n%s\n",
1495 cmd_pipeline_port_out_help);
1500 if ((strcmp(tokens[0], "pipeline") == 0) &&
1501 (n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
1502 snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
1506 if ((strcmp(tokens[0], "pipeline") == 0) &&
1508 (strcmp(tokens[1], "table") == 0) &&
1509 (strcmp(tokens[2], "update") == 0)) {
1510 snprintf(out, out_size, "\n%s\n",
1511 cmd_pipeline_table_update_help);
1515 if ((strcmp(tokens[0], "pipeline") == 0) &&
1516 (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
1517 snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
1521 if ((n_tokens == 3) &&
1522 (strcmp(tokens[0], "thread") == 0) &&
1523 (strcmp(tokens[1], "pipeline") == 0)) {
1524 if (strcmp(tokens[2], "enable") == 0) {
1525 snprintf(out, out_size, "\n%s\n",
1526 cmd_thread_pipeline_enable_help);
1530 if (strcmp(tokens[2], "disable") == 0) {
1531 snprintf(out, out_size, "\n%s\n",
1532 cmd_thread_pipeline_disable_help);
1537 snprintf(out, out_size, "Invalid command\n");
1541 cli_process(char *in, char *out, size_t out_size, void *obj)
1543 char *tokens[CMD_MAX_TOKENS];
1544 uint32_t n_tokens = RTE_DIM(tokens);
1550 status = parse_tokenize_string(in, tokens, &n_tokens);
1552 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
1559 if (strcmp(tokens[0], "help") == 0) {
1560 cmd_help(tokens, n_tokens, out, out_size, obj);
1564 if (strcmp(tokens[0], "mempool") == 0) {
1565 cmd_mempool(tokens, n_tokens, out, out_size, obj);
1569 if (strcmp(tokens[0], "link") == 0) {
1570 if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
1571 cmd_link_show(tokens, n_tokens, out, out_size, obj);
1575 cmd_link(tokens, n_tokens, out, out_size, obj);
1579 if (strcmp(tokens[0], "ring") == 0) {
1580 cmd_ring(tokens, n_tokens, out, out_size, obj);
1584 if (strcmp(tokens[0], "tap") == 0) {
1585 cmd_tap(tokens, n_tokens, out, out_size, obj);
1589 if (strcmp(tokens[0], "pipeline") == 0) {
1590 if ((n_tokens >= 3) &&
1591 (strcmp(tokens[2], "create") == 0)) {
1592 cmd_pipeline_create(tokens, n_tokens, out, out_size,
1597 if ((n_tokens >= 4) &&
1598 (strcmp(tokens[2], "port") == 0) &&
1599 (strcmp(tokens[3], "in") == 0)) {
1600 cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
1605 if ((n_tokens >= 4) &&
1606 (strcmp(tokens[2], "port") == 0) &&
1607 (strcmp(tokens[3], "out") == 0)) {
1608 cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
1613 if ((n_tokens >= 3) &&
1614 (strcmp(tokens[2], "build") == 0)) {
1615 cmd_pipeline_build(tokens, n_tokens, out, out_size,
1620 if ((n_tokens >= 3) &&
1621 (strcmp(tokens[2], "table") == 0)) {
1622 cmd_pipeline_table_update(tokens, n_tokens, out,
1627 if ((n_tokens >= 3) &&
1628 (strcmp(tokens[2], "stats") == 0)) {
1629 cmd_pipeline_stats(tokens, n_tokens, out, out_size,
1635 if (strcmp(tokens[0], "thread") == 0) {
1636 if ((n_tokens >= 5) &&
1637 (strcmp(tokens[4], "enable") == 0)) {
1638 cmd_thread_pipeline_enable(tokens, n_tokens,
1639 out, out_size, obj);
1643 if ((n_tokens >= 5) &&
1644 (strcmp(tokens[4], "disable") == 0)) {
1645 cmd_thread_pipeline_disable(tokens, n_tokens,
1646 out, out_size, obj);
1651 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
1655 cli_script_process(const char *file_name,
1656 size_t msg_in_len_max,
1657 size_t msg_out_len_max,
1660 char *msg_in = NULL, *msg_out = NULL;
1663 /* Check input arguments */
1664 if ((file_name == NULL) ||
1665 (strlen(file_name) == 0) ||
1666 (msg_in_len_max == 0) ||
1667 (msg_out_len_max == 0))
1670 msg_in = malloc(msg_in_len_max + 1);
1671 msg_out = malloc(msg_out_len_max + 1);
1672 if ((msg_in == NULL) ||
1673 (msg_out == NULL)) {
1679 /* Open input file */
1680 f = fopen(file_name, "r");
1689 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
1692 printf("%s", msg_in);
1700 if (strlen(msg_out))
1701 printf("%s", msg_out);