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_pipeline.h>
16 #include <rte_swx_ctl.h>
23 #ifndef CMD_MAX_TOKENS
24 #define CMD_MAX_TOKENS 256
27 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
28 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
29 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
30 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
31 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
32 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
33 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
34 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
35 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
36 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
37 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
39 #define skip_white_spaces(pos) \
41 __typeof__(pos) _p = (pos); \
42 for ( ; isspace(*_p); _p++) \
48 parser_read_uint64(uint64_t *value, const char *p)
53 p = skip_white_spaces(p);
57 val = strtoul(p, &next, 10);
79 p = skip_white_spaces(p);
88 parser_read_uint32(uint32_t *value, const char *p)
91 int ret = parser_read_uint64(&val, p);
104 parser_read_uint16(uint16_t *value, const char *p)
107 int ret = parser_read_uint64(&val, p);
112 if (val > UINT16_MAX)
119 #define PARSE_DELIMITER " \f\n\r\t\v"
122 parse_tokenize_string(char *string, char *tokens[], uint32_t *n_tokens)
126 if ((string == NULL) ||
131 for (i = 0; i < *n_tokens; i++) {
132 tokens[i] = strtok_r(string, PARSE_DELIMITER, &string);
133 if (tokens[i] == NULL)
137 if ((i == *n_tokens) && strtok_r(string, PARSE_DELIMITER, &string))
147 if ((strlen(in) && index("!#%;", in[0])) ||
148 (strncmp(in, "//", 2) == 0) ||
149 (strncmp(in, "--", 2) == 0))
155 static const char cmd_mempool_help[] =
156 "mempool <mempool_name>\n"
157 " buffer <buffer_size>\n"
158 " pool <pool_size>\n"
159 " cache <cache_size>\n"
163 cmd_mempool(char **tokens,
169 struct mempool_params p;
171 struct mempool *mempool;
173 if (n_tokens != 10) {
174 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
180 if (strcmp(tokens[2], "buffer") != 0) {
181 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
185 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
186 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
190 if (strcmp(tokens[4], "pool") != 0) {
191 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
195 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
196 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
200 if (strcmp(tokens[6], "cache") != 0) {
201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
205 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
206 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
210 if (strcmp(tokens[8], "cpu") != 0) {
211 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
215 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
216 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
220 mempool = mempool_create(obj, name, &p);
221 if (mempool == NULL) {
222 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
227 static const char cmd_link_help[] =
229 " dev <device_name> | port <port_id>\n"
230 " rxq <n_queues> <queue_size> <mempool_name>\n"
231 " txq <n_queues> <queue_size>\n"
232 " promiscuous on | off\n"
233 " [rss <qid_0> ... <qid_n>]\n";
236 cmd_link(char **tokens,
242 struct link_params p;
243 struct link_params_rss rss;
247 memset(&p, 0, sizeof(p));
249 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
250 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
255 if (strcmp(tokens[2], "dev") == 0)
256 p.dev_name = tokens[3];
257 else if (strcmp(tokens[2], "port") == 0) {
260 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
261 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
265 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
269 if (strcmp(tokens[4], "rxq") != 0) {
270 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
274 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
275 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
278 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
279 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
283 p.rx.mempool_name = tokens[7];
285 if (strcmp(tokens[8], "txq") != 0) {
286 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
290 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
291 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
295 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
296 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
300 if (strcmp(tokens[11], "promiscuous") != 0) {
301 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
305 if (strcmp(tokens[12], "on") == 0)
307 else if (strcmp(tokens[12], "off") == 0)
310 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
317 uint32_t queue_id, i;
319 if (strcmp(tokens[13], "rss") != 0) {
320 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
327 for (i = 14; i < n_tokens; i++) {
328 if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
329 snprintf(out, out_size, MSG_ARG_INVALID,
334 rss.queue_id[rss.n_queues] = queue_id;
339 link = link_create(obj, name, &p);
341 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
346 /* Print the link stats and info */
348 print_link_info(struct link *link, char *out, size_t out_size)
350 struct rte_eth_stats stats;
351 struct rte_ether_addr mac_addr;
352 struct rte_eth_link eth_link;
356 memset(&stats, 0, sizeof(stats));
357 rte_eth_stats_get(link->port_id, &stats);
359 ret = rte_eth_macaddr_get(link->port_id, &mac_addr);
361 snprintf(out, out_size, "\n%s: MAC address get failed: %s",
362 link->name, rte_strerror(-ret));
366 ret = rte_eth_link_get(link->port_id, ð_link);
368 snprintf(out, out_size, "\n%s: link get failed: %s",
369 link->name, rte_strerror(-ret));
373 rte_eth_dev_get_mtu(link->port_id, &mtu);
375 snprintf(out, out_size,
377 "%s: flags=<%s> mtu %u\n"
378 "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n"
379 "\tport# %u speed %s\n"
380 "\tRX packets %" PRIu64" bytes %" PRIu64"\n"
381 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
382 "\tTX packets %" PRIu64" bytes %" PRIu64"\n"
383 "\tTX errors %" PRIu64"\n",
385 eth_link.link_status == 0 ? "DOWN" : "UP",
387 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
388 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
389 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5],
393 rte_eth_link_speed_to_str(eth_link.link_speed),
405 * link show [<link_name>]
408 cmd_link_show(char **tokens,
417 if (n_tokens != 2 && n_tokens != 3) {
418 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
423 link = link_next(obj, NULL);
425 while (link != NULL) {
426 out_size = out_size - strlen(out);
427 out = &out[strlen(out)];
429 print_link_info(link, out, out_size);
430 link = link_next(obj, link);
433 out_size = out_size - strlen(out);
434 out = &out[strlen(out)];
436 link_name = tokens[2];
437 link = link_find(obj, link_name);
440 snprintf(out, out_size, MSG_ARG_INVALID,
441 "Link does not exist");
444 print_link_info(link, out, out_size);
448 static const char cmd_ring_help[] =
449 "ring <ring_name> size <size> numa <numa_node>\n";
452 cmd_ring(char **tokens,
458 struct ring_params p;
463 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
469 if (strcmp(tokens[2], "size") != 0) {
470 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
474 if (parser_read_uint32(&p.size, tokens[3]) != 0) {
475 snprintf(out, out_size, MSG_ARG_INVALID, "size");
479 if (strcmp(tokens[4], "numa") != 0) {
480 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "numa");
484 if (parser_read_uint32(&p.numa_node, tokens[5]) != 0) {
485 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
489 ring = ring_create(obj, name, &p);
491 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
496 static const char cmd_pipeline_create_help[] =
497 "pipeline <pipeline_name> create <numa_node>\n";
500 cmd_pipeline_create(char **tokens,
511 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
517 if (parser_read_uint32(&numa_node, tokens[3]) != 0) {
518 snprintf(out, out_size, MSG_ARG_INVALID, "numa_node");
522 p = pipeline_create(obj, name, (int)numa_node);
524 snprintf(out, out_size, "pipeline create error.");
529 static const char cmd_pipeline_port_in_help[] =
530 "pipeline <pipeline_name> port in <port_id>\n"
531 " link <link_name> rxq <queue_id> bsz <burst_size>\n"
532 " ring <ring_name> bsz <burst_size>\n"
533 " | source <mempool_name> <file_name>\n";
536 cmd_pipeline_port_in(char **tokens,
544 uint32_t port_id = 0, t0;
547 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
551 p = pipeline_find(obj, tokens[1]);
553 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
557 if (strcmp(tokens[2], "port") != 0) {
558 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
562 if (strcmp(tokens[3], "in") != 0) {
563 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
567 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
568 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
574 if (strcmp(tokens[t0], "link") == 0) {
575 struct rte_swx_port_ethdev_reader_params params;
578 if (n_tokens < t0 + 6) {
579 snprintf(out, out_size, MSG_ARG_MISMATCH,
580 "pipeline port in link");
584 link = link_find(obj, tokens[t0 + 1]);
586 snprintf(out, out_size, MSG_ARG_INVALID,
590 params.dev_name = link->dev_name;
592 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
593 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
597 if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
598 snprintf(out, out_size, MSG_ARG_INVALID,
603 if (strcmp(tokens[t0 + 4], "bsz") != 0) {
604 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
608 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
609 snprintf(out, out_size, MSG_ARG_INVALID,
616 status = rte_swx_pipeline_port_in_config(p->p,
620 } else if (strcmp(tokens[t0], "ring") == 0) {
621 struct rte_swx_port_ring_reader_params params;
624 if (n_tokens < t0 + 4) {
625 snprintf(out, out_size, MSG_ARG_MISMATCH,
626 "pipeline port in ring");
630 ring = ring_find(obj, tokens[t0 + 1]);
632 snprintf(out, out_size, MSG_ARG_INVALID,
636 params.name = ring->name;
638 if (strcmp(tokens[t0 + 2], "bsz") != 0) {
639 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
643 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
644 snprintf(out, out_size, MSG_ARG_INVALID,
651 status = rte_swx_pipeline_port_in_config(p->p,
655 } else if (strcmp(tokens[t0], "source") == 0) {
656 struct rte_swx_port_source_params params;
659 if (n_tokens < t0 + 3) {
660 snprintf(out, out_size, MSG_ARG_MISMATCH,
661 "pipeline port in source");
665 mp = mempool_find(obj, tokens[t0 + 1]);
667 snprintf(out, out_size, MSG_ARG_INVALID,
673 params.file_name = tokens[t0 + 2];
677 status = rte_swx_pipeline_port_in_config(p->p,
682 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
687 snprintf(out, out_size, "port in error.");
691 if (n_tokens != t0) {
692 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
697 static const char cmd_pipeline_port_out_help[] =
698 "pipeline <pipeline_name> port out <port_id>\n"
699 " link <link_name> txq <txq_id> bsz <burst_size>\n"
700 " ring <ring_name> bsz <burst_size>\n"
701 " | sink <file_name> | none\n";
704 cmd_pipeline_port_out(char **tokens,
712 uint32_t port_id = 0, t0;
715 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
719 p = pipeline_find(obj, tokens[1]);
721 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
725 if (strcmp(tokens[2], "port") != 0) {
726 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
730 if (strcmp(tokens[3], "out") != 0) {
731 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
735 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
736 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
742 if (strcmp(tokens[t0], "link") == 0) {
743 struct rte_swx_port_ethdev_writer_params params;
746 if (n_tokens < t0 + 6) {
747 snprintf(out, out_size, MSG_ARG_MISMATCH,
748 "pipeline port out link");
752 link = link_find(obj, tokens[t0 + 1]);
754 snprintf(out, out_size, MSG_ARG_INVALID,
758 params.dev_name = link->dev_name;
760 if (strcmp(tokens[t0 + 2], "txq") != 0) {
761 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
765 if (parser_read_uint16(¶ms.queue_id, tokens[t0 + 3]) != 0) {
766 snprintf(out, out_size, MSG_ARG_INVALID,
771 if (strcmp(tokens[t0 + 4], "bsz") != 0) {
772 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
776 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 5])) {
777 snprintf(out, out_size, MSG_ARG_INVALID,
784 status = rte_swx_pipeline_port_out_config(p->p,
788 } else if (strcmp(tokens[t0], "ring") == 0) {
789 struct rte_swx_port_ring_writer_params params;
792 if (n_tokens < t0 + 4) {
793 snprintf(out, out_size, MSG_ARG_MISMATCH,
794 "pipeline port out link");
798 ring = ring_find(obj, tokens[t0 + 1]);
800 snprintf(out, out_size, MSG_ARG_INVALID,
804 params.name = ring->name;
806 if (strcmp(tokens[t0 + 2], "bsz") != 0) {
807 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
811 if (parser_read_uint32(¶ms.burst_size, tokens[t0 + 3])) {
812 snprintf(out, out_size, MSG_ARG_INVALID,
819 status = rte_swx_pipeline_port_out_config(p->p,
823 } else if (strcmp(tokens[t0], "sink") == 0) {
824 struct rte_swx_port_sink_params params;
826 params.file_name = strcmp(tokens[t0 + 1], "none") ?
827 tokens[t0 + 1] : NULL;
831 status = rte_swx_pipeline_port_out_config(p->p,
836 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
841 snprintf(out, out_size, "port out error.");
845 if (n_tokens != t0) {
846 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
851 static const char cmd_pipeline_build_help[] =
852 "pipeline <pipeline_name> build <spec_file>\n";
855 cmd_pipeline_build(char **tokens,
861 struct pipeline *p = NULL;
868 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
872 p = pipeline_find(obj, tokens[1]);
874 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
878 spec = fopen(tokens[3], "r");
880 snprintf(out, out_size, "Cannot open file %s.\n", tokens[3]);
884 status = rte_swx_pipeline_build_from_spec(p->p,
890 snprintf(out, out_size, "Error %d at line %u: %s\n.",
891 status, err_line, err_msg);
895 p->ctl = rte_swx_ctl_pipeline_create(p->p);
897 snprintf(out, out_size, "Pipeline control create failed.");
898 rte_swx_pipeline_free(p->p);
904 table_entry_free(struct rte_swx_table_entry *entry)
910 free(entry->key_mask);
911 free(entry->action_data);
915 static const char cmd_pipeline_table_update_help[] =
916 "pipeline <pipeline_name> table <table_name> update <file_name_add> "
917 "<file_name_delete> <file_name_default>";
920 cmd_pipeline_table_update(char **tokens,
927 char *pipeline_name, *table_name, *line = NULL;
928 char *file_name_add, *file_name_delete, *file_name_default;
929 FILE *file_add = NULL, *file_delete = NULL, *file_default = NULL;
934 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
938 pipeline_name = tokens[1];
939 p = pipeline_find(obj, pipeline_name);
941 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
945 if (strcmp(tokens[2], "table") != 0) {
946 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
950 table_name = tokens[3];
952 if (strcmp(tokens[4], "update") != 0) {
953 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "update");
957 file_name_add = tokens[5];
958 file_name_delete = tokens[6];
959 file_name_default = tokens[7];
962 if (strcmp(file_name_add, "none")) {
963 file_add = fopen(file_name_add, "r");
965 snprintf(out, out_size, "Cannot open file %s",
971 if (strcmp(file_name_delete, "none")) {
972 file_delete = fopen(file_name_delete, "r");
974 snprintf(out, out_size, "Cannot open file %s",
980 if (strcmp(file_name_default, "none")) {
981 file_default = fopen(file_name_default, "r");
983 snprintf(out, out_size, "Cannot open file %s",
989 if (!file_add && !file_delete && !file_default) {
990 snprintf(out, out_size, "Nothing to be done.");
994 /* Buffer allocation. */
997 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
1003 for (line_id = 1; ; line_id++) {
1004 struct rte_swx_table_entry *entry;
1006 if (fgets(line, 2048, file_add) == NULL)
1009 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1013 snprintf(out, out_size, MSG_FILE_ERR,
1014 file_name_add, line_id);
1018 status = rte_swx_ctl_pipeline_table_entry_add(p->ctl,
1021 table_entry_free(entry);
1023 snprintf(out, out_size,
1024 "Invalid entry in file %s at line %u",
1025 file_name_add, line_id);
1033 for (line_id = 1; ; line_id++) {
1034 struct rte_swx_table_entry *entry;
1036 if (fgets(line, 2048, file_delete) == NULL)
1039 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1043 snprintf(out, out_size, MSG_FILE_ERR,
1044 file_name_delete, line_id);
1048 status = rte_swx_ctl_pipeline_table_entry_delete(p->ctl,
1051 table_entry_free(entry);
1053 snprintf(out, out_size,
1054 "Invalid entry in file %s at line %u",
1055 file_name_delete, line_id);
1062 for (line_id = 1; ; line_id++) {
1063 struct rte_swx_table_entry *entry;
1065 if (fgets(line, 2048, file_default) == NULL)
1068 entry = rte_swx_ctl_pipeline_table_entry_read(p->ctl,
1072 snprintf(out, out_size, MSG_FILE_ERR,
1073 file_name_default, line_id);
1077 status = rte_swx_ctl_pipeline_table_default_entry_add(p->ctl,
1080 table_entry_free(entry);
1082 snprintf(out, out_size,
1083 "Invalid entry in file %s at line %u",
1084 file_name_default, line_id);
1089 status = rte_swx_ctl_pipeline_commit(p->ctl, 1);
1091 snprintf(out, out_size, "Commit failed.");
1096 rte_swx_ctl_pipeline_table_fprintf(stdout, p->ctl, table_name);
1102 fclose(file_delete);
1104 fclose(file_default);
1108 rte_swx_ctl_pipeline_abort(p->ctl);
1113 fclose(file_delete);
1115 fclose(file_default);
1118 static const char cmd_pipeline_stats_help[] =
1119 "pipeline <pipeline_name> stats\n";
1122 cmd_pipeline_stats(char **tokens,
1128 struct rte_swx_ctl_pipeline_info info;
1133 if (n_tokens != 3) {
1134 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1138 p = pipeline_find(obj, tokens[1]);
1139 if (!p || !p->ctl) {
1140 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1144 if (strcmp(tokens[2], "stats")) {
1145 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1149 status = rte_swx_ctl_pipeline_info_get(p->p, &info);
1151 snprintf(out, out_size, "Pipeline info get error.");
1155 snprintf(out, out_size, "Input ports:\n");
1156 out_size -= strlen(out);
1159 for (i = 0; i < info.n_ports_in; i++) {
1160 struct rte_swx_port_in_stats stats;
1162 rte_swx_ctl_pipeline_port_in_stats_read(p->p, i, &stats);
1164 snprintf(out, out_size, "\tPort %u:"
1167 " empty %" PRIu64 "\n",
1168 i, stats.n_pkts, stats.n_bytes, stats.n_empty);
1169 out_size -= strlen(out);
1173 snprintf(out, out_size, "Output ports:\n");
1174 out_size -= strlen(out);
1177 for (i = 0; i < info.n_ports_out; i++) {
1178 struct rte_swx_port_out_stats stats;
1180 rte_swx_ctl_pipeline_port_out_stats_read(p->p, i, &stats);
1182 snprintf(out, out_size, "\tPort %u:"
1184 " bytes %" PRIu64 "\n",
1185 i, stats.n_pkts, stats.n_bytes);
1186 out_size -= strlen(out);
1191 static const char cmd_thread_pipeline_enable_help[] =
1192 "thread <thread_id> pipeline <pipeline_name> enable\n";
1195 cmd_thread_pipeline_enable(char **tokens,
1201 char *pipeline_name;
1206 if (n_tokens != 5) {
1207 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1211 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1212 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1216 if (strcmp(tokens[2], "pipeline") != 0) {
1217 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1221 pipeline_name = tokens[3];
1222 p = pipeline_find(obj, pipeline_name);
1223 if (!p || !p->ctl) {
1224 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1228 if (strcmp(tokens[4], "enable") != 0) {
1229 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
1233 status = thread_pipeline_enable(thread_id, obj, pipeline_name);
1235 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
1240 static const char cmd_thread_pipeline_disable_help[] =
1241 "thread <thread_id> pipeline <pipeline_name> disable\n";
1244 cmd_thread_pipeline_disable(char **tokens,
1251 char *pipeline_name;
1255 if (n_tokens != 5) {
1256 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1260 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
1261 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
1265 if (strcmp(tokens[2], "pipeline") != 0) {
1266 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
1270 pipeline_name = tokens[3];
1271 p = pipeline_find(obj, pipeline_name);
1272 if (!p || !p->ctl) {
1273 snprintf(out, out_size, MSG_ARG_INVALID, "pipeline_name");
1277 if (strcmp(tokens[4], "disable") != 0) {
1278 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
1282 status = thread_pipeline_disable(thread_id, obj, pipeline_name);
1284 snprintf(out, out_size, MSG_CMD_FAIL,
1285 "thread pipeline disable");
1291 cmd_help(char **tokens,
1295 void *arg __rte_unused)
1300 if (n_tokens == 0) {
1301 snprintf(out, out_size,
1302 "Type 'help <command>' for command details.\n\n"
1303 "List of commands:\n"
1306 "\tpipeline create\n"
1307 "\tpipeline port in\n"
1308 "\tpipeline port out\n"
1309 "\tpipeline build\n"
1310 "\tpipeline table update\n"
1311 "\tpipeline stats\n"
1312 "\tthread pipeline enable\n"
1313 "\tthread pipeline disable\n\n");
1317 if (strcmp(tokens[0], "mempool") == 0) {
1318 snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
1322 if (strcmp(tokens[0], "link") == 0) {
1323 snprintf(out, out_size, "\n%s\n", cmd_link_help);
1327 if (strcmp(tokens[0], "ring") == 0) {
1328 snprintf(out, out_size, "\n%s\n", cmd_ring_help);
1332 if ((strcmp(tokens[0], "pipeline") == 0) &&
1333 (n_tokens == 2) && (strcmp(tokens[1], "create") == 0)) {
1334 snprintf(out, out_size, "\n%s\n", cmd_pipeline_create_help);
1338 if ((strcmp(tokens[0], "pipeline") == 0) &&
1339 (n_tokens == 3) && (strcmp(tokens[1], "port") == 0)) {
1340 if (strcmp(tokens[2], "in") == 0) {
1341 snprintf(out, out_size, "\n%s\n",
1342 cmd_pipeline_port_in_help);
1346 if (strcmp(tokens[2], "out") == 0) {
1347 snprintf(out, out_size, "\n%s\n",
1348 cmd_pipeline_port_out_help);
1353 if ((strcmp(tokens[0], "pipeline") == 0) &&
1354 (n_tokens == 2) && (strcmp(tokens[1], "build") == 0)) {
1355 snprintf(out, out_size, "\n%s\n", cmd_pipeline_build_help);
1359 if ((strcmp(tokens[0], "pipeline") == 0) &&
1361 (strcmp(tokens[1], "table") == 0) &&
1362 (strcmp(tokens[2], "update") == 0)) {
1363 snprintf(out, out_size, "\n%s\n",
1364 cmd_pipeline_table_update_help);
1368 if ((strcmp(tokens[0], "pipeline") == 0) &&
1369 (n_tokens == 2) && (strcmp(tokens[1], "stats") == 0)) {
1370 snprintf(out, out_size, "\n%s\n", cmd_pipeline_stats_help);
1374 if ((n_tokens == 3) &&
1375 (strcmp(tokens[0], "thread") == 0) &&
1376 (strcmp(tokens[1], "pipeline") == 0)) {
1377 if (strcmp(tokens[2], "enable") == 0) {
1378 snprintf(out, out_size, "\n%s\n",
1379 cmd_thread_pipeline_enable_help);
1383 if (strcmp(tokens[2], "disable") == 0) {
1384 snprintf(out, out_size, "\n%s\n",
1385 cmd_thread_pipeline_disable_help);
1390 snprintf(out, out_size, "Invalid command\n");
1394 cli_process(char *in, char *out, size_t out_size, void *obj)
1396 char *tokens[CMD_MAX_TOKENS];
1397 uint32_t n_tokens = RTE_DIM(tokens);
1403 status = parse_tokenize_string(in, tokens, &n_tokens);
1405 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
1412 if (strcmp(tokens[0], "help") == 0) {
1413 cmd_help(tokens, n_tokens, out, out_size, obj);
1417 if (strcmp(tokens[0], "mempool") == 0) {
1418 cmd_mempool(tokens, n_tokens, out, out_size, obj);
1422 if (strcmp(tokens[0], "link") == 0) {
1423 if ((n_tokens >= 2) && (strcmp(tokens[1], "show") == 0)) {
1424 cmd_link_show(tokens, n_tokens, out, out_size, obj);
1428 cmd_link(tokens, n_tokens, out, out_size, obj);
1432 if (strcmp(tokens[0], "ring") == 0) {
1433 cmd_ring(tokens, n_tokens, out, out_size, obj);
1437 if (strcmp(tokens[0], "pipeline") == 0) {
1438 if ((n_tokens >= 3) &&
1439 (strcmp(tokens[2], "create") == 0)) {
1440 cmd_pipeline_create(tokens, n_tokens, out, out_size,
1445 if ((n_tokens >= 4) &&
1446 (strcmp(tokens[2], "port") == 0) &&
1447 (strcmp(tokens[3], "in") == 0)) {
1448 cmd_pipeline_port_in(tokens, n_tokens, out, out_size,
1453 if ((n_tokens >= 4) &&
1454 (strcmp(tokens[2], "port") == 0) &&
1455 (strcmp(tokens[3], "out") == 0)) {
1456 cmd_pipeline_port_out(tokens, n_tokens, out, out_size,
1461 if ((n_tokens >= 3) &&
1462 (strcmp(tokens[2], "build") == 0)) {
1463 cmd_pipeline_build(tokens, n_tokens, out, out_size,
1468 if ((n_tokens >= 3) &&
1469 (strcmp(tokens[2], "table") == 0)) {
1470 cmd_pipeline_table_update(tokens, n_tokens, out,
1475 if ((n_tokens >= 3) &&
1476 (strcmp(tokens[2], "stats") == 0)) {
1477 cmd_pipeline_stats(tokens, n_tokens, out, out_size,
1483 if (strcmp(tokens[0], "thread") == 0) {
1484 if ((n_tokens >= 5) &&
1485 (strcmp(tokens[4], "enable") == 0)) {
1486 cmd_thread_pipeline_enable(tokens, n_tokens,
1487 out, out_size, obj);
1491 if ((n_tokens >= 5) &&
1492 (strcmp(tokens[4], "disable") == 0)) {
1493 cmd_thread_pipeline_disable(tokens, n_tokens,
1494 out, out_size, obj);
1499 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
1503 cli_script_process(const char *file_name,
1504 size_t msg_in_len_max,
1505 size_t msg_out_len_max,
1508 char *msg_in = NULL, *msg_out = NULL;
1511 /* Check input arguments */
1512 if ((file_name == NULL) ||
1513 (strlen(file_name) == 0) ||
1514 (msg_in_len_max == 0) ||
1515 (msg_out_len_max == 0))
1518 msg_in = malloc(msg_in_len_max + 1);
1519 msg_out = malloc(msg_out_len_max + 1);
1520 if ((msg_in == NULL) ||
1521 (msg_out == NULL)) {
1527 /* Open input file */
1528 f = fopen(file_name, "r");
1537 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
1540 printf("%s", msg_in);
1548 if (strlen(msg_out))
1549 printf("%s", msg_out);