1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
10 #include <rte_common.h>
11 #include <rte_cycles.h>
12 #include <rte_ethdev.h>
25 #ifndef CMD_MAX_TOKENS
26 #define CMD_MAX_TOKENS 256
29 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
30 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
31 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
32 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
33 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
34 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
35 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
36 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
37 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
38 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
39 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
44 if ((strlen(in) && index("!#%;", in[0])) ||
45 (strncmp(in, "//", 2) == 0) ||
46 (strncmp(in, "--", 2) == 0))
52 static const char cmd_mempool_help[] =
53 "mempool <mempool_name>\n"
54 " buffer <buffer_size>\n"
56 " cache <cache_size>\n"
60 cmd_mempool(char **tokens,
65 struct mempool_params p;
67 struct mempool *mempool;
70 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
76 if (strcmp(tokens[2], "buffer") != 0) {
77 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
81 if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
82 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
86 if (strcmp(tokens[4], "pool") != 0) {
87 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
91 if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
92 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
96 if (strcmp(tokens[6], "cache") != 0) {
97 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
101 if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
102 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
106 if (strcmp(tokens[8], "cpu") != 0) {
107 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
111 if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) {
112 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
116 mempool = mempool_create(name, &p);
117 if (mempool == NULL) {
118 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
123 static const char cmd_link_help[] =
125 " dev <device_name> | port <port_id>\n"
126 " rxq <n_queues> <queue_size> <mempool_name>\n"
127 " txq <n_queues> <queue_size>\n"
128 " promiscuous on | off\n"
129 " [rss <qid_0> ... <qid_n>]\n";
132 cmd_link(char **tokens,
137 struct link_params p;
138 struct link_params_rss rss;
142 memset(&p, 0, sizeof(p));
144 if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) {
145 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
150 if (strcmp(tokens[2], "dev") == 0)
151 p.dev_name = tokens[3];
152 else if (strcmp(tokens[2], "port") == 0) {
155 if (parser_read_uint16(&p.port_id, tokens[3]) != 0) {
156 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
160 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
164 if (strcmp(tokens[4], "rxq") != 0) {
165 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
169 if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) {
170 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
173 if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) {
174 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
178 p.rx.mempool_name = tokens[7];
180 if (strcmp(tokens[8], "txq") != 0) {
181 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
185 if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) {
186 snprintf(out, out_size, MSG_ARG_INVALID, "n_queues");
190 if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) {
191 snprintf(out, out_size, MSG_ARG_INVALID, "queue_size");
195 if (strcmp(tokens[11], "promiscuous") != 0) {
196 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous");
200 if (strcmp(tokens[12], "on") == 0)
202 else if (strcmp(tokens[12], "off") == 0)
205 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off");
212 uint32_t queue_id, i;
214 if (strcmp(tokens[13], "rss") != 0) {
215 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss");
222 for (i = 14; i < n_tokens; i++) {
223 if (parser_read_uint32(&queue_id, tokens[i]) != 0) {
224 snprintf(out, out_size, MSG_ARG_INVALID,
229 rss.queue_id[rss.n_queues] = queue_id;
234 link = link_create(name, &p);
236 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
241 /* Print the link stats and info */
243 print_link_info(struct link *link, char *out, size_t out_size)
245 struct rte_eth_stats stats;
246 struct ether_addr mac_addr;
247 struct rte_eth_link eth_link;
250 memset(&stats, 0, sizeof(stats));
251 rte_eth_stats_get(link->port_id, &stats);
253 rte_eth_macaddr_get(link->port_id, &mac_addr);
254 rte_eth_link_get(link->port_id, ð_link);
255 rte_eth_dev_get_mtu(link->port_id, &mtu);
257 snprintf(out, out_size,
259 "%s: flags=<%s> mtu %u\n"
260 "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n"
261 "\tport# %u speed %u Mbps\n"
262 "\tRX packets %" PRIu64" bytes %" PRIu64"\n"
263 "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n"
264 "\tTX packets %" PRIu64" bytes %" PRIu64"\n"
265 "\tTX errors %" PRIu64"\n",
267 eth_link.link_status == 0 ? "DOWN" : "UP",
269 mac_addr.addr_bytes[0], mac_addr.addr_bytes[1],
270 mac_addr.addr_bytes[2], mac_addr.addr_bytes[3],
271 mac_addr.addr_bytes[4], mac_addr.addr_bytes[5],
287 * link show [<link_name>]
290 cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size)
295 if (n_tokens != 2 && n_tokens != 3) {
296 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
301 link = link_next(NULL);
303 while (link != NULL) {
304 out_size = out_size - strlen(out);
305 out = &out[strlen(out)];
307 print_link_info(link, out, out_size);
308 link = link_next(link);
311 out_size = out_size - strlen(out);
312 out = &out[strlen(out)];
314 link_name = tokens[2];
315 link = link_find(link_name);
318 snprintf(out, out_size, MSG_ARG_INVALID,
319 "Link does not exist");
322 print_link_info(link, out, out_size);
326 static const char cmd_swq_help[] =
332 cmd_swq(char **tokens,
342 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
348 if (strcmp(tokens[2], "size") != 0) {
349 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
353 if (parser_read_uint32(&p.size, tokens[3]) != 0) {
354 snprintf(out, out_size, MSG_ARG_INVALID, "size");
358 if (strcmp(tokens[4], "cpu") != 0) {
359 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
363 if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) {
364 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
368 swq = swq_create(name, &p);
370 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
375 static const char cmd_tmgr_subport_profile_help[] =
376 "tmgr subport profile\n"
377 " <tb_rate> <tb_size>\n"
378 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n"
382 cmd_tmgr_subport_profile(char **tokens,
387 struct rte_sched_subport_params p;
390 if (n_tokens != 10) {
391 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
395 if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) {
396 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
400 if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) {
401 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
405 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
406 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) {
407 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
411 if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) {
412 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
416 status = tmgr_subport_profile_add(&p);
418 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
423 static const char cmd_tmgr_pipe_profile_help[] =
424 "tmgr pipe profile\n"
425 " <tb_rate> <tb_size>\n"
426 " <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n"
429 " <wrr_weight0..15>\n";
432 cmd_tmgr_pipe_profile(char **tokens,
437 struct rte_sched_pipe_params p;
440 if (n_tokens != 27) {
441 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
445 if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) {
446 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
450 if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) {
451 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
455 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
456 if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) {
457 snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate");
461 if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) {
462 snprintf(out, out_size, MSG_ARG_INVALID, "tc_period");
466 #ifdef RTE_SCHED_SUBPORT_TC_OV
467 if (parser_read_uint8(&p.tc_ov_weight, tokens[10]) != 0) {
468 snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight");
473 for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++)
474 if (parser_read_uint8(&p.wrr_weights[i], tokens[11 + i]) != 0) {
475 snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights");
479 status = tmgr_pipe_profile_add(&p);
481 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
486 static const char cmd_tmgr_help[] =
489 " spp <n_subports_per_port>\n"
490 " pps <n_pipes_per_subport>\n"
491 " qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3>\n"
492 " fo <frame_overhead>\n"
497 cmd_tmgr(char **tokens,
502 struct tmgr_port_params p;
504 struct tmgr_port *tmgr_port;
507 if (n_tokens != 19) {
508 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
514 if (strcmp(tokens[2], "rate") != 0) {
515 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
519 if (parser_read_uint32(&p.rate, tokens[3]) != 0) {
520 snprintf(out, out_size, MSG_ARG_INVALID, "rate");
524 if (strcmp(tokens[4], "spp") != 0) {
525 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
529 if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) {
530 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port");
534 if (strcmp(tokens[6], "pps") != 0) {
535 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
539 if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) {
540 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport");
544 if (strcmp(tokens[8], "qsize") != 0) {
545 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize");
549 for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++)
550 if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) {
551 snprintf(out, out_size, MSG_ARG_INVALID, "qsize");
555 if (strcmp(tokens[13], "fo") != 0) {
556 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo");
560 if (parser_read_uint32(&p.frame_overhead, tokens[14]) != 0) {
561 snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead");
565 if (strcmp(tokens[15], "mtu") != 0) {
566 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu");
570 if (parser_read_uint32(&p.mtu, tokens[16]) != 0) {
571 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
575 if (strcmp(tokens[17], "cpu") != 0) {
576 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
580 if (parser_read_uint32(&p.cpu_id, tokens[18]) != 0) {
581 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
585 tmgr_port = tmgr_port_create(name, &p);
586 if (tmgr_port == NULL) {
587 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
592 static const char cmd_tmgr_subport_help[] =
593 "tmgr <tmgr_name> subport <subport_id>\n"
594 " profile <subport_profile_id>\n";
597 cmd_tmgr_subport(char **tokens,
602 uint32_t subport_id, subport_profile_id;
607 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
613 if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
614 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
618 if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) {
619 snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id");
623 status = tmgr_subport_config(name, subport_id, subport_profile_id);
625 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
631 static const char cmd_tmgr_subport_pipe_help[] =
632 "tmgr <tmgr_name> subport <subport_id> pipe\n"
633 " from <pipe_id_first> to <pipe_id_last>\n"
634 " profile <pipe_profile_id>\n";
637 cmd_tmgr_subport_pipe(char **tokens,
642 uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id;
646 if (n_tokens != 11) {
647 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
653 if (parser_read_uint32(&subport_id, tokens[3]) != 0) {
654 snprintf(out, out_size, MSG_ARG_INVALID, "subport_id");
658 if (strcmp(tokens[4], "pipe") != 0) {
659 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe");
663 if (strcmp(tokens[5], "from") != 0) {
664 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from");
668 if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) {
669 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first");
673 if (strcmp(tokens[7], "to") != 0) {
674 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to");
678 if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) {
679 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last");
683 if (strcmp(tokens[9], "profile") != 0) {
684 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
688 if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) {
689 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id");
693 status = tmgr_pipe_config(name, subport_id, pipe_id_first,
694 pipe_id_last, pipe_profile_id);
696 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
702 static const char cmd_tap_help[] =
706 cmd_tap(char **tokens,
715 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
721 tap = tap_create(name);
723 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
728 static const char cmd_kni_help[] =
730 " link <link_name>\n"
731 " mempool <mempool_name>\n"
732 " [thread <thread_id>]\n";
735 cmd_kni(char **tokens,
744 memset(&p, 0, sizeof(p));
745 if ((n_tokens != 6) && (n_tokens != 8)) {
746 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
752 if (strcmp(tokens[2], "link") != 0) {
753 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link");
757 p.link_name = tokens[3];
759 if (strcmp(tokens[4], "mempool") != 0) {
760 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool");
764 p.mempool_name = tokens[5];
767 if (strcmp(tokens[6], "thread") != 0) {
768 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread");
772 if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) {
773 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
781 kni = kni_create(name, &p);
783 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
789 static const char cmd_port_in_action_profile_help[] =
790 "port in action profile <profile_name>\n"
791 " [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n"
792 " [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\n";
795 cmd_port_in_action_profile(char **tokens,
800 struct port_in_action_profile_params p;
801 struct port_in_action_profile *ap;
805 memset(&p, 0, sizeof(p));
808 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
812 if (strcmp(tokens[1], "in") != 0) {
813 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
817 if (strcmp(tokens[2], "action") != 0) {
818 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
822 if (strcmp(tokens[3], "profile") != 0) {
823 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
831 if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) {
834 if (n_tokens < t0 + 10) {
835 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
839 if (strcmp(tokens[t0 + 1], "match") == 0)
840 p.fltr.filter_on_match = 1;
841 else if (strcmp(tokens[t0 + 1], "mismatch") == 0)
842 p.fltr.filter_on_match = 0;
844 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
848 if (strcmp(tokens[t0 + 2], "offset") != 0) {
849 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
853 if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) {
854 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
858 if (strcmp(tokens[t0 + 4], "mask") != 0) {
859 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
863 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
864 if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) ||
865 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
866 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
870 if (strcmp(tokens[t0 + 6], "key") != 0) {
871 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
875 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
876 if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) ||
877 (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) {
878 snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
882 if (strcmp(tokens[t0 + 8], "port") != 0) {
883 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
887 if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) {
888 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
892 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
896 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) {
899 if (n_tokens < t0 + 22) {
900 snprintf(out, out_size, MSG_ARG_MISMATCH,
901 "port in action profile balance");
905 if (strcmp(tokens[t0 + 1], "offset") != 0) {
906 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
910 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) {
911 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
915 if (strcmp(tokens[t0 + 3], "mask") != 0) {
916 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
920 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
921 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) {
922 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
926 if (strcmp(tokens[t0 + 5], "port") != 0) {
927 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
931 for (i = 0; i < 16; i++)
932 if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) {
933 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
937 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
942 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
946 ap = port_in_action_profile_create(name, &p);
948 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
954 static const char cmd_table_action_profile_help[] =
955 "table action profile <profile_name>\n"
957 " offset <ip_offset>\n"
959 " [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n"
960 " [meter srtcm | trtcm\n"
962 " stats none | pkts | bytes | both]\n"
963 " [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\n"
964 " [encap ether | vlan | qinq | mpls | pppoe |\n"
965 " vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off]\n"
967 " proto udp | tcp]\n"
969 " stats none | pkts]\n"
970 " [stats pkts | bytes | both]\n"
974 cmd_table_action_profile(char **tokens,
979 struct table_action_profile_params p;
980 struct table_action_profile *ap;
984 memset(&p, 0, sizeof(p));
987 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
991 if (strcmp(tokens[1], "action") != 0) {
992 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
996 if (strcmp(tokens[2], "profile") != 0) {
997 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
1003 if (strcmp(tokens[4], "ipv4") == 0)
1004 p.common.ip_version = 1;
1005 else if (strcmp(tokens[4], "ipv6") == 0)
1006 p.common.ip_version = 0;
1008 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
1012 if (strcmp(tokens[5], "offset") != 0) {
1013 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1017 if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) {
1018 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
1022 if (strcmp(tokens[7], "fwd") != 0) {
1023 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
1027 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
1030 if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) {
1031 if (n_tokens < t0 + 7) {
1032 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
1036 if (strcmp(tokens[t0 + 1], "offset") != 0) {
1037 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1041 if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) {
1042 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1046 if (strcmp(tokens[t0 + 3], "mask") != 0) {
1047 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1051 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
1052 if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) {
1053 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1057 if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
1058 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
1062 if (parser_read_uint32(&p.lb.out_offset, tokens[t0 + 6]) != 0) {
1063 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
1067 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
1071 if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) {
1072 if (n_tokens < t0 + 6) {
1073 snprintf(out, out_size, MSG_ARG_MISMATCH,
1074 "table action profile meter");
1078 if (strcmp(tokens[t0 + 1], "srtcm") == 0)
1079 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
1080 else if (strcmp(tokens[t0 + 1], "trtcm") == 0)
1081 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
1083 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1088 if (strcmp(tokens[t0 + 2], "tc") != 0) {
1089 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
1093 if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) {
1094 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
1098 if (strcmp(tokens[t0 + 4], "stats") != 0) {
1099 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1103 if (strcmp(tokens[t0 + 5], "none") == 0) {
1104 p.mtr.n_packets_enabled = 0;
1105 p.mtr.n_bytes_enabled = 0;
1106 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
1107 p.mtr.n_packets_enabled = 1;
1108 p.mtr.n_bytes_enabled = 0;
1109 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
1110 p.mtr.n_packets_enabled = 0;
1111 p.mtr.n_bytes_enabled = 1;
1112 } else if (strcmp(tokens[t0 + 5], "both") == 0) {
1113 p.mtr.n_packets_enabled = 1;
1114 p.mtr.n_bytes_enabled = 1;
1116 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1117 "none or pkts or bytes or both");
1121 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
1125 if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) {
1126 if (n_tokens < t0 + 5) {
1127 snprintf(out, out_size, MSG_ARG_MISMATCH,
1128 "table action profile tm");
1132 if (strcmp(tokens[t0 + 1], "spp") != 0) {
1133 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
1137 if (parser_read_uint32(&p.tm.n_subports_per_port,
1138 tokens[t0 + 2]) != 0) {
1139 snprintf(out, out_size, MSG_ARG_INVALID,
1140 "n_subports_per_port");
1144 if (strcmp(tokens[t0 + 3], "pps") != 0) {
1145 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
1149 if (parser_read_uint32(&p.tm.n_pipes_per_subport,
1150 tokens[t0 + 4]) != 0) {
1151 snprintf(out, out_size, MSG_ARG_INVALID,
1152 "n_pipes_per_subport");
1156 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
1160 if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) {
1161 uint32_t n_extra_tokens = 0;
1163 if (n_tokens < t0 + 2) {
1164 snprintf(out, out_size, MSG_ARG_MISMATCH,
1165 "action profile encap");
1169 if (strcmp(tokens[t0 + 1], "ether") == 0)
1170 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
1171 else if (strcmp(tokens[t0 + 1], "vlan") == 0)
1172 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
1173 else if (strcmp(tokens[t0 + 1], "qinq") == 0)
1174 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
1175 else if (strcmp(tokens[t0 + 1], "mpls") == 0)
1176 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
1177 else if (strcmp(tokens[t0 + 1], "pppoe") == 0)
1178 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
1179 else if (strcmp(tokens[t0 + 1], "vxlan") == 0) {
1180 if (n_tokens < t0 + 2 + 5) {
1181 snprintf(out, out_size, MSG_ARG_MISMATCH,
1182 "action profile encap vxlan");
1186 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1187 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1192 if (parser_read_uint32(&p.encap.vxlan.data_offset,
1193 tokens[t0 + 2 + 1]) != 0) {
1194 snprintf(out, out_size, MSG_ARG_INVALID,
1195 "vxlan: ether_offset");
1199 if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0)
1200 p.encap.vxlan.ip_version = 1;
1201 else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0)
1202 p.encap.vxlan.ip_version = 0;
1204 snprintf(out, out_size, MSG_ARG_INVALID,
1205 "vxlan: ipv4 or ipv6");
1209 if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) {
1210 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1215 if (strcmp(tokens[t0 + 2 + 4], "on") == 0)
1216 p.encap.vxlan.vlan = 1;
1217 else if (strcmp(tokens[t0 + 2 + 4], "off") == 0)
1218 p.encap.vxlan.vlan = 0;
1220 snprintf(out, out_size, MSG_ARG_INVALID,
1221 "vxlan: on or off");
1225 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN;
1228 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
1232 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
1233 t0 += 2 + n_extra_tokens;
1236 if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) {
1237 if (n_tokens < t0 + 4) {
1238 snprintf(out, out_size, MSG_ARG_MISMATCH,
1239 "table action profile nat");
1243 if (strcmp(tokens[t0 + 1], "src") == 0)
1244 p.nat.source_nat = 1;
1245 else if (strcmp(tokens[t0 + 1], "dst") == 0)
1246 p.nat.source_nat = 0;
1248 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1253 if (strcmp(tokens[t0 + 2], "proto") != 0) {
1254 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
1258 if (strcmp(tokens[t0 + 3], "tcp") == 0)
1260 else if (strcmp(tokens[t0 + 3], "udp") == 0)
1263 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1268 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
1272 if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) {
1273 if (n_tokens < t0 + 4) {
1274 snprintf(out, out_size, MSG_ARG_MISMATCH,
1275 "table action profile ttl");
1279 if (strcmp(tokens[t0 + 1], "drop") == 0)
1281 else if (strcmp(tokens[t0 + 1], "fwd") == 0)
1284 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1289 if (strcmp(tokens[t0 + 2], "stats") != 0) {
1290 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1294 if (strcmp(tokens[t0 + 3], "none") == 0)
1295 p.ttl.n_packets_enabled = 0;
1296 else if (strcmp(tokens[t0 + 3], "pkts") == 0)
1297 p.ttl.n_packets_enabled = 1;
1299 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1304 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
1308 if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) {
1309 if (n_tokens < t0 + 2) {
1310 snprintf(out, out_size, MSG_ARG_MISMATCH,
1311 "table action profile stats");
1315 if (strcmp(tokens[t0 + 1], "pkts") == 0) {
1316 p.stats.n_packets_enabled = 1;
1317 p.stats.n_bytes_enabled = 0;
1318 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
1319 p.stats.n_packets_enabled = 0;
1320 p.stats.n_bytes_enabled = 1;
1321 } else if (strcmp(tokens[t0 + 1], "both") == 0) {
1322 p.stats.n_packets_enabled = 1;
1323 p.stats.n_bytes_enabled = 1;
1325 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1326 "pkts or bytes or both");
1330 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
1334 if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) {
1335 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
1339 if (t0 < n_tokens) {
1340 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1344 ap = table_action_profile_create(name, &p);
1346 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1351 static const char cmd_pipeline_help[] =
1352 "pipeline <pipeline_name>\n"
1353 " period <timer_period_ms>\n"
1354 " offset_port_id <offset_port_id>\n"
1358 cmd_pipeline(char **tokens,
1363 struct pipeline_params p;
1365 struct pipeline *pipeline;
1367 if (n_tokens != 8) {
1368 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1374 if (strcmp(tokens[2], "period") != 0) {
1375 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
1379 if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) {
1380 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
1384 if (strcmp(tokens[4], "offset_port_id") != 0) {
1385 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
1389 if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) {
1390 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
1394 if (strcmp(tokens[6], "cpu") != 0) {
1395 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu");
1399 if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) {
1400 snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id");
1404 pipeline = pipeline_create(name, &p);
1405 if (pipeline == NULL) {
1406 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1411 static const char cmd_pipeline_port_in_help[] =
1412 "pipeline <pipeline_name> port in\n"
1413 " bsz <burst_size>\n"
1414 " link <link_name> rxq <queue_id>\n"
1415 " | swq <swq_name>\n"
1416 " | tmgr <tmgr_name>\n"
1417 " | tap <tap_name> mempool <mempool_name> mtu <mtu>\n"
1418 " | kni <kni_name>\n"
1419 " | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n"
1420 " [action <port_in_action_profile_name>]\n"
1424 cmd_pipeline_port_in(char **tokens,
1429 struct port_in_params p;
1430 char *pipeline_name;
1432 int enabled, status;
1435 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1439 pipeline_name = tokens[1];
1441 if (strcmp(tokens[2], "port") != 0) {
1442 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1446 if (strcmp(tokens[3], "in") != 0) {
1447 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1451 if (strcmp(tokens[4], "bsz") != 0) {
1452 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1456 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1457 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1463 if (strcmp(tokens[t0], "link") == 0) {
1464 if (n_tokens < t0 + 4) {
1465 snprintf(out, out_size, MSG_ARG_MISMATCH,
1466 "pipeline port in link");
1470 p.type = PORT_IN_RXQ;
1472 p.dev_name = tokens[t0 + 1];
1474 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
1475 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
1479 if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) {
1480 snprintf(out, out_size, MSG_ARG_INVALID,
1485 } else if (strcmp(tokens[t0], "swq") == 0) {
1486 if (n_tokens < t0 + 2) {
1487 snprintf(out, out_size, MSG_ARG_MISMATCH,
1488 "pipeline port in swq");
1492 p.type = PORT_IN_SWQ;
1494 p.dev_name = tokens[t0 + 1];
1497 } else if (strcmp(tokens[t0], "tmgr") == 0) {
1498 if (n_tokens < t0 + 2) {
1499 snprintf(out, out_size, MSG_ARG_MISMATCH,
1500 "pipeline port in tmgr");
1504 p.type = PORT_IN_TMGR;
1506 p.dev_name = tokens[t0 + 1];
1509 } else if (strcmp(tokens[t0], "tap") == 0) {
1510 if (n_tokens < t0 + 6) {
1511 snprintf(out, out_size, MSG_ARG_MISMATCH,
1512 "pipeline port in tap");
1516 p.type = PORT_IN_TAP;
1518 p.dev_name = tokens[t0 + 1];
1520 if (strcmp(tokens[t0 + 2], "mempool") != 0) {
1521 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1526 p.tap.mempool_name = tokens[t0 + 3];
1528 if (strcmp(tokens[t0 + 4], "mtu") != 0) {
1529 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1534 if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) {
1535 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
1540 } else if (strcmp(tokens[t0], "kni") == 0) {
1541 if (n_tokens < t0 + 2) {
1542 snprintf(out, out_size, MSG_ARG_MISMATCH,
1543 "pipeline port in kni");
1547 p.type = PORT_IN_KNI;
1549 p.dev_name = tokens[t0 + 1];
1552 } else if (strcmp(tokens[t0], "source") == 0) {
1553 if (n_tokens < t0 + 6) {
1554 snprintf(out, out_size, MSG_ARG_MISMATCH,
1555 "pipeline port in source");
1559 p.type = PORT_IN_SOURCE;
1563 if (strcmp(tokens[t0 + 1], "mempool") != 0) {
1564 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1569 p.source.mempool_name = tokens[t0 + 2];
1571 if (strcmp(tokens[t0 + 3], "file") != 0) {
1572 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1577 p.source.file_name = tokens[t0 + 4];
1579 if (strcmp(tokens[t0 + 5], "bpp") != 0) {
1580 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1585 if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) {
1586 snprintf(out, out_size, MSG_ARG_INVALID,
1593 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1597 p.action_profile_name = NULL;
1598 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
1599 if (n_tokens < t0 + 2) {
1600 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1604 p.action_profile_name = tokens[t0 + 1];
1610 if ((n_tokens > t0) &&
1611 (strcmp(tokens[t0], "disabled") == 0)) {
1617 if (n_tokens != t0) {
1618 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1622 status = pipeline_port_in_create(pipeline_name,
1625 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1630 static const char cmd_pipeline_port_out_help[] =
1631 "pipeline <pipeline_name> port out\n"
1632 " bsz <burst_size>\n"
1633 " link <link_name> txq <txq_id>\n"
1634 " | swq <swq_name>\n"
1635 " | tmgr <tmgr_name>\n"
1636 " | tap <tap_name>\n"
1637 " | kni <kni_name>\n"
1638 " | sink [file <file_name> pkts <max_n_pkts>]\n";
1641 cmd_pipeline_port_out(char **tokens,
1646 struct port_out_params p;
1647 char *pipeline_name;
1650 memset(&p, 0, sizeof(p));
1653 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1657 pipeline_name = tokens[1];
1659 if (strcmp(tokens[2], "port") != 0) {
1660 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1664 if (strcmp(tokens[3], "out") != 0) {
1665 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
1669 if (strcmp(tokens[4], "bsz") != 0) {
1670 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1674 if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1675 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1679 if (strcmp(tokens[6], "link") == 0) {
1680 if (n_tokens != 10) {
1681 snprintf(out, out_size, MSG_ARG_MISMATCH,
1682 "pipeline port out link");
1686 p.type = PORT_OUT_TXQ;
1688 p.dev_name = tokens[7];
1690 if (strcmp(tokens[8], "txq") != 0) {
1691 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
1695 if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) {
1696 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1699 } else if (strcmp(tokens[6], "swq") == 0) {
1700 if (n_tokens != 8) {
1701 snprintf(out, out_size, MSG_ARG_MISMATCH,
1702 "pipeline port out swq");
1706 p.type = PORT_OUT_SWQ;
1708 p.dev_name = tokens[7];
1709 } else if (strcmp(tokens[6], "tmgr") == 0) {
1710 if (n_tokens != 8) {
1711 snprintf(out, out_size, MSG_ARG_MISMATCH,
1712 "pipeline port out tmgr");
1716 p.type = PORT_OUT_TMGR;
1718 p.dev_name = tokens[7];
1719 } else if (strcmp(tokens[6], "tap") == 0) {
1720 if (n_tokens != 8) {
1721 snprintf(out, out_size, MSG_ARG_MISMATCH,
1722 "pipeline port out tap");
1726 p.type = PORT_OUT_TAP;
1728 p.dev_name = tokens[7];
1729 } else if (strcmp(tokens[6], "kni") == 0) {
1730 if (n_tokens != 8) {
1731 snprintf(out, out_size, MSG_ARG_MISMATCH,
1732 "pipeline port out kni");
1736 p.type = PORT_OUT_KNI;
1738 p.dev_name = tokens[7];
1739 } else if (strcmp(tokens[6], "sink") == 0) {
1740 if ((n_tokens != 7) && (n_tokens != 11)) {
1741 snprintf(out, out_size, MSG_ARG_MISMATCH,
1742 "pipeline port out sink");
1746 p.type = PORT_OUT_SINK;
1750 if (n_tokens == 7) {
1751 p.sink.file_name = NULL;
1752 p.sink.max_n_pkts = 0;
1754 if (strcmp(tokens[7], "file") != 0) {
1755 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1760 p.sink.file_name = tokens[8];
1762 if (strcmp(tokens[9], "pkts") != 0) {
1763 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
1767 if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) {
1768 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
1773 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1777 status = pipeline_port_out_create(pipeline_name, &p);
1779 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1784 static const char cmd_pipeline_table_help[] =
1785 "pipeline <pipeline_name> table\n"
1789 " offset <ip_header_offset>\n"
1792 " offset <key_offset>\n"
1797 " mask <key_mask>\n"
1798 " offset <key_offset>\n"
1799 " buckets <n_buckets>\n"
1803 " offset <ip_header_offset>\n"
1806 " [action <table_action_profile_name>]\n";
1809 cmd_pipeline_table(char **tokens,
1814 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
1815 struct table_params p;
1816 char *pipeline_name;
1821 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1825 pipeline_name = tokens[1];
1827 if (strcmp(tokens[2], "table") != 0) {
1828 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1832 if (strcmp(tokens[3], "match") != 0) {
1833 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
1838 if (strcmp(tokens[t0], "acl") == 0) {
1839 if (n_tokens < t0 + 6) {
1840 snprintf(out, out_size, MSG_ARG_MISMATCH,
1841 "pipeline table acl");
1845 p.match_type = TABLE_ACL;
1847 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
1848 p.match.acl.ip_version = 1;
1849 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
1850 p.match.acl.ip_version = 0;
1852 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1857 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1858 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1862 if (parser_read_uint32(&p.match.acl.ip_header_offset,
1863 tokens[t0 + 3]) != 0) {
1864 snprintf(out, out_size, MSG_ARG_INVALID,
1865 "ip_header_offset");
1869 if (strcmp(tokens[t0 + 4], "size") != 0) {
1870 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1874 if (parser_read_uint32(&p.match.acl.n_rules,
1875 tokens[t0 + 5]) != 0) {
1876 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
1881 } else if (strcmp(tokens[t0], "array") == 0) {
1882 if (n_tokens < t0 + 5) {
1883 snprintf(out, out_size, MSG_ARG_MISMATCH,
1884 "pipeline table array");
1888 p.match_type = TABLE_ARRAY;
1890 if (strcmp(tokens[t0 + 1], "offset") != 0) {
1891 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1895 if (parser_read_uint32(&p.match.array.key_offset,
1896 tokens[t0 + 2]) != 0) {
1897 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1901 if (strcmp(tokens[t0 + 3], "size") != 0) {
1902 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1906 if (parser_read_uint32(&p.match.array.n_keys,
1907 tokens[t0 + 4]) != 0) {
1908 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1913 } else if (strcmp(tokens[t0], "hash") == 0) {
1914 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
1916 if (n_tokens < t0 + 12) {
1917 snprintf(out, out_size, MSG_ARG_MISMATCH,
1918 "pipeline table hash");
1922 p.match_type = TABLE_HASH;
1924 if (strcmp(tokens[t0 + 1], "ext") == 0)
1925 p.match.hash.extendable_bucket = 1;
1926 else if (strcmp(tokens[t0 + 1], "lru") == 0)
1927 p.match.hash.extendable_bucket = 0;
1929 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1934 if (strcmp(tokens[t0 + 2], "key") != 0) {
1935 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
1939 if ((parser_read_uint32(&p.match.hash.key_size,
1940 tokens[t0 + 3]) != 0) ||
1941 (p.match.hash.key_size == 0) ||
1942 (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) {
1943 snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
1947 if (strcmp(tokens[t0 + 4], "mask") != 0) {
1948 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1952 if ((parse_hex_string(tokens[t0 + 5],
1953 key_mask, &key_mask_size) != 0) ||
1954 (key_mask_size != p.match.hash.key_size)) {
1955 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1958 p.match.hash.key_mask = key_mask;
1960 if (strcmp(tokens[t0 + 6], "offset") != 0) {
1961 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1965 if (parser_read_uint32(&p.match.hash.key_offset,
1966 tokens[t0 + 7]) != 0) {
1967 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1971 if (strcmp(tokens[t0 + 8], "buckets") != 0) {
1972 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
1976 if (parser_read_uint32(&p.match.hash.n_buckets,
1977 tokens[t0 + 9]) != 0) {
1978 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
1982 if (strcmp(tokens[t0 + 10], "size") != 0) {
1983 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1987 if (parser_read_uint32(&p.match.hash.n_keys,
1988 tokens[t0 + 11]) != 0) {
1989 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1994 } else if (strcmp(tokens[t0], "lpm") == 0) {
1995 if (n_tokens < t0 + 6) {
1996 snprintf(out, out_size, MSG_ARG_MISMATCH,
1997 "pipeline table lpm");
2001 p.match_type = TABLE_LPM;
2003 if (strcmp(tokens[t0 + 1], "ipv4") == 0)
2004 p.match.lpm.key_size = 4;
2005 else if (strcmp(tokens[t0 + 1], "ipv6") == 0)
2006 p.match.lpm.key_size = 16;
2008 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2013 if (strcmp(tokens[t0 + 2], "offset") != 0) {
2014 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
2018 if (parser_read_uint32(&p.match.lpm.key_offset,
2019 tokens[t0 + 3]) != 0) {
2020 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
2024 if (strcmp(tokens[t0 + 4], "size") != 0) {
2025 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
2029 if (parser_read_uint32(&p.match.lpm.n_rules,
2030 tokens[t0 + 5]) != 0) {
2031 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
2036 } else if (strcmp(tokens[t0], "stub") == 0) {
2037 p.match_type = TABLE_STUB;
2041 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
2045 p.action_profile_name = NULL;
2046 if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) {
2047 if (n_tokens < t0 + 2) {
2048 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
2052 p.action_profile_name = tokens[t0 + 1];
2057 if (n_tokens > t0) {
2058 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2062 status = pipeline_table_create(pipeline_name, &p);
2064 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2069 static const char cmd_pipeline_port_in_table_help[] =
2070 "pipeline <pipeline_name> port in <port_id> table <table_id>\n";
2073 cmd_pipeline_port_in_table(char **tokens,
2078 char *pipeline_name;
2079 uint32_t port_id, table_id;
2082 if (n_tokens != 7) {
2083 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2087 pipeline_name = tokens[1];
2089 if (strcmp(tokens[2], "port") != 0) {
2090 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2094 if (strcmp(tokens[3], "in") != 0) {
2095 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2099 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2100 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2104 if (strcmp(tokens[5], "table") != 0) {
2105 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
2109 if (parser_read_uint32(&table_id, tokens[6]) != 0) {
2110 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
2114 status = pipeline_port_in_connect_to_table(pipeline_name,
2118 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2124 static const char cmd_pipeline_port_in_stats_help[] =
2125 "pipeline <pipeline_name> port in <port_id> stats read [clear]\n";
2127 #define MSG_PIPELINE_PORT_IN_STATS \
2128 "Pkts in: %" PRIu64 "\n" \
2129 "Pkts dropped by AH: %" PRIu64 "\n" \
2130 "Pkts dropped by other: %" PRIu64 "\n"
2133 cmd_pipeline_port_in_stats(char **tokens,
2138 struct rte_pipeline_port_in_stats stats;
2139 char *pipeline_name;
2143 if ((n_tokens != 7) && (n_tokens != 8)) {
2144 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2148 pipeline_name = tokens[1];
2150 if (strcmp(tokens[2], "port") != 0) {
2151 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2155 if (strcmp(tokens[3], "in") != 0) {
2156 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2160 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2161 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2165 if (strcmp(tokens[5], "stats") != 0) {
2166 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2170 if (strcmp(tokens[6], "read") != 0) {
2171 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2176 if (n_tokens == 8) {
2177 if (strcmp(tokens[7], "clear") != 0) {
2178 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2185 status = pipeline_port_in_stats_read(pipeline_name,
2190 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2194 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
2195 stats.stats.n_pkts_in,
2196 stats.n_pkts_dropped_by_ah,
2197 stats.stats.n_pkts_drop);
2201 static const char cmd_pipeline_port_in_enable_help[] =
2202 "pipeline <pipeline_name> port in <port_id> enable\n";
2205 cmd_pipeline_port_in_enable(char **tokens,
2210 char *pipeline_name;
2214 if (n_tokens != 6) {
2215 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2219 pipeline_name = tokens[1];
2221 if (strcmp(tokens[2], "port") != 0) {
2222 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2226 if (strcmp(tokens[3], "in") != 0) {
2227 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2231 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2232 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2236 if (strcmp(tokens[5], "enable") != 0) {
2237 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
2241 status = pipeline_port_in_enable(pipeline_name, port_id);
2243 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2249 static const char cmd_pipeline_port_in_disable_help[] =
2250 "pipeline <pipeline_name> port in <port_id> disable\n";
2253 cmd_pipeline_port_in_disable(char **tokens,
2258 char *pipeline_name;
2262 if (n_tokens != 6) {
2263 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2267 pipeline_name = tokens[1];
2269 if (strcmp(tokens[2], "port") != 0) {
2270 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2274 if (strcmp(tokens[3], "in") != 0) {
2275 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2279 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2280 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2284 if (strcmp(tokens[5], "disable") != 0) {
2285 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2289 status = pipeline_port_in_disable(pipeline_name, port_id);
2291 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2297 static const char cmd_pipeline_port_out_stats_help[] =
2298 "pipeline <pipeline_name> port out <port_id> stats read [clear]\n";
2300 #define MSG_PIPELINE_PORT_OUT_STATS \
2301 "Pkts in: %" PRIu64 "\n" \
2302 "Pkts dropped by AH: %" PRIu64 "\n" \
2303 "Pkts dropped by other: %" PRIu64 "\n"
2306 cmd_pipeline_port_out_stats(char **tokens,
2311 struct rte_pipeline_port_out_stats stats;
2312 char *pipeline_name;
2316 if ((n_tokens != 7) && (n_tokens != 8)) {
2317 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2321 pipeline_name = tokens[1];
2323 if (strcmp(tokens[2], "port") != 0) {
2324 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2328 if (strcmp(tokens[3], "out") != 0) {
2329 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
2333 if (parser_read_uint32(&port_id, tokens[4]) != 0) {
2334 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2338 if (strcmp(tokens[5], "stats") != 0) {
2339 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2343 if (strcmp(tokens[6], "read") != 0) {
2344 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2349 if (n_tokens == 8) {
2350 if (strcmp(tokens[7], "clear") != 0) {
2351 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2358 status = pipeline_port_out_stats_read(pipeline_name,
2363 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2367 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
2368 stats.stats.n_pkts_in,
2369 stats.n_pkts_dropped_by_ah,
2370 stats.stats.n_pkts_drop);
2374 static const char cmd_pipeline_table_stats_help[] =
2375 "pipeline <pipeline_name> table <table_id> stats read [clear]\n";
2377 #define MSG_PIPELINE_TABLE_STATS \
2378 "Pkts in: %" PRIu64 "\n" \
2379 "Pkts in with lookup miss: %" PRIu64 "\n" \
2380 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \
2381 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \
2382 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \
2383 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
2386 cmd_pipeline_table_stats(char **tokens,
2391 struct rte_pipeline_table_stats stats;
2392 char *pipeline_name;
2396 if ((n_tokens != 6) && (n_tokens != 7)) {
2397 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2401 pipeline_name = tokens[1];
2403 if (strcmp(tokens[2], "table") != 0) {
2404 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2408 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
2409 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
2413 if (strcmp(tokens[4], "stats") != 0) {
2414 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2418 if (strcmp(tokens[5], "read") != 0) {
2419 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2424 if (n_tokens == 7) {
2425 if (strcmp(tokens[6], "clear") != 0) {
2426 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2433 status = pipeline_table_stats_read(pipeline_name,
2438 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2442 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
2443 stats.stats.n_pkts_in,
2444 stats.stats.n_pkts_lookup_miss,
2445 stats.n_pkts_dropped_by_lkp_hit_ah,
2446 stats.n_pkts_dropped_lkp_hit,
2447 stats.n_pkts_dropped_by_lkp_miss_ah,
2448 stats.n_pkts_dropped_lkp_miss);
2456 * priority <priority>
2457 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
2458 * <sp0> <sp1> <dp0> <dp1> <proto>
2462 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
2463 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
2464 * | ipv4_addr <addr>
2465 * | ipv6_addr <addr>
2466 * | qinq <svlan> <cvlan>
2468 * ipv4 | ipv6 <addr> <depth>
2470 struct pkt_key_qinq {
2471 uint16_t ethertype_svlan;
2473 uint16_t ethertype_cvlan;
2475 } __attribute__((__packed__));
2477 struct pkt_key_ipv4_5tuple {
2478 uint8_t time_to_live;
2480 uint16_t hdr_checksum;
2485 } __attribute__((__packed__));
2487 struct pkt_key_ipv6_5tuple {
2488 uint16_t payload_length;
2495 } __attribute__((__packed__));
2497 struct pkt_key_ipv4_addr {
2499 } __attribute__((__packed__));
2501 struct pkt_key_ipv6_addr {
2503 } __attribute__((__packed__));
2506 parse_match(char **tokens,
2510 struct table_rule_match *m)
2512 memset(m, 0, sizeof(*m));
2517 if (strcmp(tokens[0], "match") != 0) {
2518 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
2522 if (strcmp(tokens[1], "acl") == 0) {
2523 if (n_tokens < 14) {
2524 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2528 m->match_type = TABLE_ACL;
2530 if (strcmp(tokens[2], "priority") != 0) {
2531 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
2535 if (parser_read_uint32(&m->match.acl.priority,
2537 snprintf(out, out_size, MSG_ARG_INVALID, "priority");
2541 if (strcmp(tokens[4], "ipv4") == 0) {
2542 struct in_addr saddr, daddr;
2544 m->match.acl.ip_version = 1;
2546 if (parse_ipv4_addr(tokens[5], &saddr) != 0) {
2547 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2550 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
2552 if (parse_ipv4_addr(tokens[7], &daddr) != 0) {
2553 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2556 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
2557 } else if (strcmp(tokens[4], "ipv6") == 0) {
2558 struct in6_addr saddr, daddr;
2560 m->match.acl.ip_version = 0;
2562 if (parse_ipv6_addr(tokens[5], &saddr) != 0) {
2563 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2566 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
2568 if (parse_ipv6_addr(tokens[7], &daddr) != 0) {
2569 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2572 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
2574 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2579 if (parser_read_uint32(&m->match.acl.sa_depth,
2581 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
2585 if (parser_read_uint32(&m->match.acl.da_depth,
2587 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
2591 if (parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
2592 snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
2596 if (parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
2597 snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
2601 if (parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
2602 snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
2606 if (parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
2607 snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
2611 if (parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
2612 snprintf(out, out_size, MSG_ARG_INVALID, "proto");
2616 m->match.acl.proto_mask = 0xff;
2621 if (strcmp(tokens[1], "array") == 0) {
2623 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2627 m->match_type = TABLE_ARRAY;
2629 if (parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
2630 snprintf(out, out_size, MSG_ARG_INVALID, "pos");
2637 if (strcmp(tokens[1], "hash") == 0) {
2639 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2643 m->match_type = TABLE_HASH;
2645 if (strcmp(tokens[2], "raw") == 0) {
2646 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
2649 snprintf(out, out_size, MSG_ARG_MISMATCH,
2654 if (parse_hex_string(tokens[3],
2655 m->match.hash.key, &key_size) != 0) {
2656 snprintf(out, out_size, MSG_ARG_INVALID, "key");
2663 if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
2664 struct pkt_key_ipv4_5tuple *ipv4 =
2665 (struct pkt_key_ipv4_5tuple *) m->match.hash.key;
2666 struct in_addr saddr, daddr;
2671 snprintf(out, out_size, MSG_ARG_MISMATCH,
2676 if (parse_ipv4_addr(tokens[3], &saddr) != 0) {
2677 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2681 if (parse_ipv4_addr(tokens[4], &daddr) != 0) {
2682 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2686 if (parser_read_uint16(&sp, tokens[5]) != 0) {
2687 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2691 if (parser_read_uint16(&dp, tokens[6]) != 0) {
2692 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2696 if (parser_read_uint8(&proto, tokens[7]) != 0) {
2697 snprintf(out, out_size, MSG_ARG_INVALID,
2702 ipv4->sa = saddr.s_addr;
2703 ipv4->da = daddr.s_addr;
2704 ipv4->sp = rte_cpu_to_be_16(sp);
2705 ipv4->dp = rte_cpu_to_be_16(dp);
2706 ipv4->proto = proto;
2709 } /* hash ipv4_5tuple */
2711 if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
2712 struct pkt_key_ipv6_5tuple *ipv6 =
2713 (struct pkt_key_ipv6_5tuple *) m->match.hash.key;
2714 struct in6_addr saddr, daddr;
2719 snprintf(out, out_size, MSG_ARG_MISMATCH,
2724 if (parse_ipv6_addr(tokens[3], &saddr) != 0) {
2725 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2729 if (parse_ipv6_addr(tokens[4], &daddr) != 0) {
2730 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2734 if (parser_read_uint16(&sp, tokens[5]) != 0) {
2735 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2739 if (parser_read_uint16(&dp, tokens[6]) != 0) {
2740 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2744 if (parser_read_uint8(&proto, tokens[7]) != 0) {
2745 snprintf(out, out_size, MSG_ARG_INVALID,
2750 memcpy(ipv6->sa, saddr.s6_addr, 16);
2751 memcpy(ipv6->da, daddr.s6_addr, 16);
2752 ipv6->sp = rte_cpu_to_be_16(sp);
2753 ipv6->dp = rte_cpu_to_be_16(dp);
2754 ipv6->proto = proto;
2757 } /* hash ipv6_5tuple */
2759 if (strcmp(tokens[2], "ipv4_addr") == 0) {
2760 struct pkt_key_ipv4_addr *ipv4_addr =
2761 (struct pkt_key_ipv4_addr *) m->match.hash.key;
2762 struct in_addr addr;
2765 snprintf(out, out_size, MSG_ARG_MISMATCH,
2770 if (parse_ipv4_addr(tokens[3], &addr) != 0) {
2771 snprintf(out, out_size, MSG_ARG_INVALID,
2776 ipv4_addr->addr = addr.s_addr;
2779 } /* hash ipv4_addr */
2781 if (strcmp(tokens[2], "ipv6_addr") == 0) {
2782 struct pkt_key_ipv6_addr *ipv6_addr =
2783 (struct pkt_key_ipv6_addr *) m->match.hash.key;
2784 struct in6_addr addr;
2787 snprintf(out, out_size, MSG_ARG_MISMATCH,
2792 if (parse_ipv6_addr(tokens[3], &addr) != 0) {
2793 snprintf(out, out_size, MSG_ARG_INVALID,
2798 memcpy(ipv6_addr->addr, addr.s6_addr, 16);
2801 } /* hash ipv6_5tuple */
2803 if (strcmp(tokens[2], "qinq") == 0) {
2804 struct pkt_key_qinq *qinq =
2805 (struct pkt_key_qinq *) m->match.hash.key;
2806 uint16_t svlan, cvlan;
2809 snprintf(out, out_size, MSG_ARG_MISMATCH,
2814 if ((parser_read_uint16(&svlan, tokens[3]) != 0) ||
2816 snprintf(out, out_size, MSG_ARG_INVALID,
2821 if ((parser_read_uint16(&cvlan, tokens[4]) != 0) ||
2823 snprintf(out, out_size, MSG_ARG_INVALID,
2828 qinq->svlan = rte_cpu_to_be_16(svlan);
2829 qinq->cvlan = rte_cpu_to_be_16(cvlan);
2834 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2838 if (strcmp(tokens[1], "lpm") == 0) {
2840 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2844 m->match_type = TABLE_LPM;
2846 if (strcmp(tokens[2], "ipv4") == 0) {
2847 struct in_addr addr;
2849 m->match.lpm.ip_version = 1;
2851 if (parse_ipv4_addr(tokens[3], &addr) != 0) {
2852 snprintf(out, out_size, MSG_ARG_INVALID,
2857 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
2858 } else if (strcmp(tokens[2], "ipv6") == 0) {
2859 struct in6_addr addr;
2861 m->match.lpm.ip_version = 0;
2863 if (parse_ipv6_addr(tokens[3], &addr) != 0) {
2864 snprintf(out, out_size, MSG_ARG_INVALID,
2869 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
2871 snprintf(out, out_size, MSG_ARG_MISMATCH,
2876 if (parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
2877 snprintf(out, out_size, MSG_ARG_INVALID, "depth");
2884 snprintf(out, out_size, MSG_ARG_MISMATCH,
2885 "acl or array or hash or lpm");
2897 * | table <table_id>
2898 * [balance <out0> ... <out7>]
2900 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2901 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2902 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2903 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
2904 * [tm subport <subport_id> pipe <pipe_id>]
2907 * | vlan <da> <sa> <pcp> <dei> <vid>
2908 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
2909 * | mpls unicast | multicast
2911 * label0 <label> <tc> <ttl>
2912 * [label1 <label> <tc> <ttl>
2913 * [label2 <label> <tc> <ttl>
2914 * [label3 <label> <tc> <ttl>]]]
2915 * | pppoe <da> <sa> <session_id>
2916 * | vxlan ether <da> <sa>
2917 * [vlan <pcp> <dei> <vid>]
2918 * ipv4 <sa> <da> <dscp> <ttl>
2919 * | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit>
2922 * [nat ipv4 | ipv6 <addr> <port>]
2928 * <pa> ::= g | y | r | drop
2931 parse_table_action_fwd(char **tokens,
2933 struct table_rule_action *a)
2935 if ((n_tokens == 0) || (strcmp(tokens[0], "fwd") != 0))
2941 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
2942 a->fwd.action = RTE_PIPELINE_ACTION_DROP;
2943 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2947 if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
2950 if ((n_tokens < 2) ||
2951 parser_read_uint32(&id, tokens[1]))
2954 a->fwd.action = RTE_PIPELINE_ACTION_PORT;
2956 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2960 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
2961 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
2962 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2966 if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
2969 if ((n_tokens < 2) ||
2970 parser_read_uint32(&id, tokens[1]))
2973 a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
2975 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2983 parse_table_action_balance(char **tokens,
2985 struct table_rule_action *a)
2989 if ((n_tokens == 0) || (strcmp(tokens[0], "balance") != 0))
2995 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
2998 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
2999 if (parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
3002 a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
3003 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
3008 parse_policer_action(char *token, enum rte_table_action_policer *a)
3010 if (strcmp(token, "g") == 0) {
3011 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
3015 if (strcmp(token, "y") == 0) {
3016 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
3020 if (strcmp(token, "r") == 0) {
3021 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
3025 if (strcmp(token, "drop") == 0) {
3026 *a = RTE_TABLE_ACTION_POLICER_DROP;
3034 parse_table_action_meter_tc(char **tokens,
3036 struct rte_table_action_mtr_tc_params *mtr)
3038 if ((n_tokens < 9) ||
3039 strcmp(tokens[0], "meter") ||
3040 parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
3041 strcmp(tokens[2], "policer") ||
3042 strcmp(tokens[3], "g") ||
3043 parse_policer_action(tokens[4], &mtr->policer[e_RTE_METER_GREEN]) ||
3044 strcmp(tokens[5], "y") ||
3045 parse_policer_action(tokens[6], &mtr->policer[e_RTE_METER_YELLOW]) ||
3046 strcmp(tokens[7], "r") ||
3047 parse_policer_action(tokens[8], &mtr->policer[e_RTE_METER_RED]))
3054 parse_table_action_meter(char **tokens,
3056 struct table_rule_action *a)
3058 if ((n_tokens == 0) || strcmp(tokens[0], "meter"))
3064 if ((n_tokens < 10) ||
3065 strcmp(tokens[0], "tc0") ||
3066 (parse_table_action_meter_tc(tokens + 1,
3068 &a->mtr.mtr[0]) == 0))
3074 if ((n_tokens == 0) || strcmp(tokens[0], "tc1")) {
3076 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
3080 if ((n_tokens < 30) ||
3081 (parse_table_action_meter_tc(tokens + 1,
3082 n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
3083 strcmp(tokens[10], "tc2") ||
3084 (parse_table_action_meter_tc(tokens + 11,
3085 n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
3086 strcmp(tokens[20], "tc3") ||
3087 (parse_table_action_meter_tc(tokens + 21,
3088 n_tokens - 21, &a->mtr.mtr[3]) == 0))
3091 a->mtr.tc_mask = 0xF;
3092 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
3093 return 1 + 10 + 3 * 10;
3097 parse_table_action_tm(char **tokens,
3099 struct table_rule_action *a)
3101 uint32_t subport_id, pipe_id;
3103 if ((n_tokens < 5) ||
3104 strcmp(tokens[0], "tm") ||
3105 strcmp(tokens[1], "subport") ||
3106 parser_read_uint32(&subport_id, tokens[2]) ||
3107 strcmp(tokens[3], "pipe") ||
3108 parser_read_uint32(&pipe_id, tokens[4]))
3111 a->tm.subport_id = subport_id;
3112 a->tm.pipe_id = pipe_id;
3113 a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
3118 parse_table_action_encap(char **tokens,
3120 struct table_rule_action *a)
3122 if ((n_tokens == 0) || strcmp(tokens[0], "encap"))
3129 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
3130 if ((n_tokens < 3) ||
3131 parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
3132 parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
3135 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
3136 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3141 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
3142 uint32_t pcp, dei, vid;
3144 if ((n_tokens < 6) ||
3145 parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
3146 parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
3147 parser_read_uint32(&pcp, tokens[3]) ||
3149 parser_read_uint32(&dei, tokens[4]) ||
3151 parser_read_uint32(&vid, tokens[5]) ||
3155 a->encap.vlan.vlan.pcp = pcp & 0x7;
3156 a->encap.vlan.vlan.dei = dei & 0x1;
3157 a->encap.vlan.vlan.vid = vid & 0xFFF;
3158 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
3159 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3164 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
3165 uint32_t svlan_pcp, svlan_dei, svlan_vid;
3166 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
3168 if ((n_tokens < 9) ||
3169 parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
3170 parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
3171 parser_read_uint32(&svlan_pcp, tokens[3]) ||
3172 (svlan_pcp > 0x7) ||
3173 parser_read_uint32(&svlan_dei, tokens[4]) ||
3174 (svlan_dei > 0x1) ||
3175 parser_read_uint32(&svlan_vid, tokens[5]) ||
3176 (svlan_vid > 0xFFF) ||
3177 parser_read_uint32(&cvlan_pcp, tokens[6]) ||
3178 (cvlan_pcp > 0x7) ||
3179 parser_read_uint32(&cvlan_dei, tokens[7]) ||
3180 (cvlan_dei > 0x1) ||
3181 parser_read_uint32(&cvlan_vid, tokens[8]) ||
3182 (cvlan_vid > 0xFFF))
3185 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
3186 a->encap.qinq.svlan.dei = svlan_dei & 0x1;
3187 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
3188 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
3189 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
3190 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
3191 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
3192 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3197 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
3198 uint32_t label, tc, ttl;
3203 if (strcmp(tokens[1], "unicast") == 0)
3204 a->encap.mpls.unicast = 1;
3205 else if (strcmp(tokens[1], "multicast") == 0)
3206 a->encap.mpls.unicast = 0;
3210 if (parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
3211 parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
3212 strcmp(tokens[4], "label0") ||
3213 parser_read_uint32(&label, tokens[5]) ||
3214 (label > 0xFFFFF) ||
3215 parser_read_uint32(&tc, tokens[6]) ||
3217 parser_read_uint32(&ttl, tokens[7]) ||
3221 a->encap.mpls.mpls[0].label = label;
3222 a->encap.mpls.mpls[0].tc = tc;
3223 a->encap.mpls.mpls[0].ttl = ttl;
3228 if ((n_tokens == 0) || strcmp(tokens[0], "label1")) {
3229 a->encap.mpls.mpls_count = 1;
3230 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3231 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3235 if ((n_tokens < 4) ||
3236 parser_read_uint32(&label, tokens[1]) ||
3237 (label > 0xFFFFF) ||
3238 parser_read_uint32(&tc, tokens[2]) ||
3240 parser_read_uint32(&ttl, tokens[3]) ||
3244 a->encap.mpls.mpls[1].label = label;
3245 a->encap.mpls.mpls[1].tc = tc;
3246 a->encap.mpls.mpls[1].ttl = ttl;
3251 if ((n_tokens == 0) || strcmp(tokens[0], "label2")) {
3252 a->encap.mpls.mpls_count = 2;
3253 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3254 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3258 if ((n_tokens < 4) ||
3259 parser_read_uint32(&label, tokens[1]) ||
3260 (label > 0xFFFFF) ||
3261 parser_read_uint32(&tc, tokens[2]) ||
3263 parser_read_uint32(&ttl, tokens[3]) ||
3267 a->encap.mpls.mpls[2].label = label;
3268 a->encap.mpls.mpls[2].tc = tc;
3269 a->encap.mpls.mpls[2].ttl = ttl;
3274 if ((n_tokens == 0) || strcmp(tokens[0], "label3")) {
3275 a->encap.mpls.mpls_count = 3;
3276 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3277 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3278 return 1 + 8 + 4 + 4;
3281 if ((n_tokens < 4) ||
3282 parser_read_uint32(&label, tokens[1]) ||
3283 (label > 0xFFFFF) ||
3284 parser_read_uint32(&tc, tokens[2]) ||
3286 parser_read_uint32(&ttl, tokens[3]) ||
3290 a->encap.mpls.mpls[3].label = label;
3291 a->encap.mpls.mpls[3].tc = tc;
3292 a->encap.mpls.mpls[3].ttl = ttl;
3294 a->encap.mpls.mpls_count = 4;
3295 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3296 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3297 return 1 + 8 + 4 + 4 + 4;
3301 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
3302 if ((n_tokens < 4) ||
3303 parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
3304 parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
3305 parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
3309 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
3310 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3315 if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) {
3322 /* ether <da> <sa> */
3323 if ((n_tokens < 3) ||
3324 strcmp(tokens[0], "ether") ||
3325 parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) ||
3326 parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa))
3333 /* [vlan <pcp> <dei> <vid>] */
3334 if (strcmp(tokens[0], "vlan") == 0) {
3335 uint32_t pcp, dei, vid;
3337 if ((n_tokens < 4) ||
3338 parser_read_uint32(&pcp, tokens[1]) ||
3340 parser_read_uint32(&dei, tokens[2]) ||
3342 parser_read_uint32(&vid, tokens[3]) ||
3346 a->encap.vxlan.vlan.pcp = pcp;
3347 a->encap.vxlan.vlan.dei = dei;
3348 a->encap.vxlan.vlan.vid = vid;
3355 /* ipv4 <sa> <da> <dscp> <ttl>
3356 | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */
3357 if (strcmp(tokens[0], "ipv4") == 0) {
3358 struct in_addr sa, da;
3361 if ((n_tokens < 5) ||
3362 parse_ipv4_addr(tokens[1], &sa) ||
3363 parse_ipv4_addr(tokens[2], &da) ||
3364 parser_read_uint8(&dscp, tokens[3]) ||
3366 parser_read_uint8(&ttl, tokens[4]))
3369 a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr);
3370 a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr);
3371 a->encap.vxlan.ipv4.dscp = dscp;
3372 a->encap.vxlan.ipv4.ttl = ttl;
3377 } else if (strcmp(tokens[0], "ipv6") == 0) {
3378 struct in6_addr sa, da;
3379 uint32_t flow_label;
3380 uint8_t dscp, hop_limit;
3382 if ((n_tokens < 6) ||
3383 parse_ipv6_addr(tokens[1], &sa) ||
3384 parse_ipv6_addr(tokens[2], &da) ||
3385 parser_read_uint32(&flow_label, tokens[3]) ||
3386 parser_read_uint8(&dscp, tokens[4]) ||
3388 parser_read_uint8(&hop_limit, tokens[5]))
3391 memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16);
3392 memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16);
3393 a->encap.vxlan.ipv6.flow_label = flow_label;
3394 a->encap.vxlan.ipv6.dscp = dscp;
3395 a->encap.vxlan.ipv6.hop_limit = hop_limit;
3404 if ((n_tokens < 3) ||
3405 strcmp(tokens[0], "udp") ||
3406 parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) ||
3407 parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2]))
3415 if ((n_tokens < 2) ||
3416 strcmp(tokens[0], "vxlan") ||
3417 parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) ||
3418 (a->encap.vxlan.vxlan.vni > 0xFFFFFF))
3425 a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN;
3426 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3434 parse_table_action_nat(char **tokens,
3436 struct table_rule_action *a)
3438 if ((n_tokens < 4) ||
3439 strcmp(tokens[0], "nat"))
3442 if (strcmp(tokens[1], "ipv4") == 0) {
3443 struct in_addr addr;
3446 if (parse_ipv4_addr(tokens[2], &addr) ||
3447 parser_read_uint16(&port, tokens[3]))
3450 a->nat.ip_version = 1;
3451 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
3453 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3457 if (strcmp(tokens[1], "ipv6") == 0) {
3458 struct in6_addr addr;
3461 if (parse_ipv6_addr(tokens[2], &addr) ||
3462 parser_read_uint16(&port, tokens[3]))
3465 a->nat.ip_version = 0;
3466 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
3468 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3476 parse_table_action_ttl(char **tokens,
3478 struct table_rule_action *a)
3480 if ((n_tokens < 2) ||
3481 strcmp(tokens[0], "ttl"))
3484 if (strcmp(tokens[1], "dec") == 0)
3485 a->ttl.decrement = 1;
3486 else if (strcmp(tokens[1], "keep") == 0)
3487 a->ttl.decrement = 0;
3491 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
3496 parse_table_action_stats(char **tokens,
3498 struct table_rule_action *a)
3500 if ((n_tokens < 1) ||
3501 strcmp(tokens[0], "stats"))
3504 a->stats.n_packets = 0;
3505 a->stats.n_bytes = 0;
3506 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
3511 parse_table_action_time(char **tokens,
3513 struct table_rule_action *a)
3515 if ((n_tokens < 1) ||
3516 strcmp(tokens[0], "time"))
3519 a->time.time = rte_rdtsc();
3520 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
3525 parse_table_action(char **tokens,
3529 struct table_rule_action *a)
3531 uint32_t n_tokens0 = n_tokens;
3533 memset(a, 0, sizeof(*a));
3535 if ((n_tokens < 2) ||
3536 strcmp(tokens[0], "action"))
3542 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
3545 n = parse_table_action_fwd(tokens, n_tokens, a);
3547 snprintf(out, out_size, MSG_ARG_INVALID,
3556 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
3559 n = parse_table_action_balance(tokens, n_tokens, a);
3561 snprintf(out, out_size, MSG_ARG_INVALID,
3570 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
3573 n = parse_table_action_meter(tokens, n_tokens, a);
3575 snprintf(out, out_size, MSG_ARG_INVALID,
3584 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
3587 n = parse_table_action_tm(tokens, n_tokens, a);
3589 snprintf(out, out_size, MSG_ARG_INVALID,
3598 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
3601 n = parse_table_action_encap(tokens, n_tokens, a);
3603 snprintf(out, out_size, MSG_ARG_INVALID,
3612 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
3615 n = parse_table_action_nat(tokens, n_tokens, a);
3617 snprintf(out, out_size, MSG_ARG_INVALID,
3626 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
3629 n = parse_table_action_ttl(tokens, n_tokens, a);
3631 snprintf(out, out_size, MSG_ARG_INVALID,
3640 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
3643 n = parse_table_action_stats(tokens, n_tokens, a);
3645 snprintf(out, out_size, MSG_ARG_INVALID,
3654 if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
3657 n = parse_table_action_time(tokens, n_tokens, a);
3659 snprintf(out, out_size, MSG_ARG_INVALID,
3668 if (n_tokens0 - n_tokens == 1) {
3669 snprintf(out, out_size, MSG_ARG_INVALID, "action");
3673 return n_tokens0 - n_tokens;
3677 static const char cmd_pipeline_table_rule_add_help[] =
3678 "pipeline <pipeline_name> table <table_id> rule add\n"
3680 " action <table_action>\n";
3683 cmd_pipeline_table_rule_add(char **tokens,
3688 struct table_rule_match m;
3689 struct table_rule_action a;
3690 char *pipeline_name;
3692 uint32_t table_id, t0, n_tokens_parsed;
3696 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3700 pipeline_name = tokens[1];
3702 if (strcmp(tokens[2], "table") != 0) {
3703 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3707 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
3708 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3712 if (strcmp(tokens[4], "rule") != 0) {
3713 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3717 if (strcmp(tokens[5], "add") != 0) {
3718 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3725 n_tokens_parsed = parse_match(tokens + t0,
3730 if (n_tokens_parsed == 0)
3732 t0 += n_tokens_parsed;
3735 n_tokens_parsed = parse_table_action(tokens + t0,
3740 if (n_tokens_parsed == 0)
3742 t0 += n_tokens_parsed;
3744 if (t0 != n_tokens) {
3745 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
3749 status = pipeline_table_rule_add(pipeline_name, table_id,
3752 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3758 static const char cmd_pipeline_table_rule_add_default_help[] =
3759 "pipeline <pipeline_name> table <table_id> rule add\n"
3765 " | port <port_id>\n"
3767 " | table <table_id>\n";
3770 cmd_pipeline_table_rule_add_default(char **tokens,
3775 struct table_rule_action action;
3777 char *pipeline_name;
3781 if ((n_tokens != 11) && (n_tokens != 12)) {
3782 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3786 pipeline_name = tokens[1];
3788 if (strcmp(tokens[2], "table") != 0) {
3789 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3793 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
3794 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3798 if (strcmp(tokens[4], "rule") != 0) {
3799 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3803 if (strcmp(tokens[5], "add") != 0) {
3804 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3808 if (strcmp(tokens[6], "match") != 0) {
3809 snprintf(out, out_size, MSG_ARG_INVALID, "match");
3813 if (strcmp(tokens[7], "default") != 0) {
3814 snprintf(out, out_size, MSG_ARG_INVALID, "default");
3818 if (strcmp(tokens[8], "action") != 0) {
3819 snprintf(out, out_size, MSG_ARG_INVALID, "action");
3823 if (strcmp(tokens[9], "fwd") != 0) {
3824 snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
3828 action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
3830 if (strcmp(tokens[10], "drop") == 0) {
3831 if (n_tokens != 11) {
3832 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3836 action.fwd.action = RTE_PIPELINE_ACTION_DROP;
3837 } else if (strcmp(tokens[10], "port") == 0) {
3840 if (n_tokens != 12) {
3841 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3845 if (parser_read_uint32(&id, tokens[11]) != 0) {
3846 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
3850 action.fwd.action = RTE_PIPELINE_ACTION_PORT;
3852 } else if (strcmp(tokens[10], "meta") == 0) {
3853 if (n_tokens != 11) {
3854 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3858 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
3859 } else if (strcmp(tokens[10], "table") == 0) {
3862 if (n_tokens != 12) {
3863 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3867 if (parser_read_uint32(&id, tokens[11]) != 0) {
3868 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3872 action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
3875 snprintf(out, out_size, MSG_ARG_INVALID,
3876 "drop or port or meta or table");
3880 status = pipeline_table_rule_add_default(pipeline_name,
3885 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3891 static const char cmd_pipeline_table_rule_add_bulk_help[] =
3892 "pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>\n"
3894 " File <file_name>:\n"
3895 " - line format: match <match> action <action>\n";
3898 cli_rule_file_process(const char *file_name,
3899 size_t line_len_max,
3900 struct table_rule_match *m,
3901 struct table_rule_action *a,
3903 uint32_t *line_number,
3908 cmd_pipeline_table_rule_add_bulk(char **tokens,
3913 struct table_rule_match *match;
3914 struct table_rule_action *action;
3916 char *pipeline_name, *file_name;
3917 uint32_t table_id, n_rules, n_rules_parsed, line_number;
3920 if (n_tokens != 9) {
3921 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3925 pipeline_name = tokens[1];
3927 if (strcmp(tokens[2], "table") != 0) {
3928 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3932 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
3933 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3937 if (strcmp(tokens[4], "rule") != 0) {
3938 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3942 if (strcmp(tokens[5], "add") != 0) {
3943 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3947 if (strcmp(tokens[6], "bulk") != 0) {
3948 snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
3952 file_name = tokens[7];
3954 if ((parser_read_uint32(&n_rules, tokens[8]) != 0) ||
3956 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
3960 /* Memory allocation. */
3961 match = calloc(n_rules, sizeof(struct table_rule_match));
3962 action = calloc(n_rules, sizeof(struct table_rule_action));
3963 data = calloc(n_rules, sizeof(void *));
3964 if ((match == NULL) || (action == NULL) || (data == NULL)) {
3965 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
3972 /* Load rule file */
3973 n_rules_parsed = n_rules;
3974 status = cli_rule_file_process(file_name,
3983 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
3989 if (n_rules_parsed != n_rules) {
3990 snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
3998 status = pipeline_table_rule_add_bulk(pipeline_name,
4005 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4019 static const char cmd_pipeline_table_rule_delete_help[] =
4020 "pipeline <pipeline_name> table <table_id> rule delete\n"
4024 cmd_pipeline_table_rule_delete(char **tokens,
4029 struct table_rule_match m;
4030 char *pipeline_name;
4031 uint32_t table_id, n_tokens_parsed, t0;
4035 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4039 pipeline_name = tokens[1];
4041 if (strcmp(tokens[2], "table") != 0) {
4042 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4046 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4047 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4051 if (strcmp(tokens[4], "rule") != 0) {
4052 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4056 if (strcmp(tokens[5], "delete") != 0) {
4057 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4064 n_tokens_parsed = parse_match(tokens + t0,
4069 if (n_tokens_parsed == 0)
4071 t0 += n_tokens_parsed;
4073 if (n_tokens != t0) {
4074 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4078 status = pipeline_table_rule_delete(pipeline_name,
4082 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4088 static const char cmd_pipeline_table_rule_delete_default_help[] =
4089 "pipeline <pipeline_name> table <table_id> rule delete\n"
4094 cmd_pipeline_table_rule_delete_default(char **tokens,
4099 char *pipeline_name;
4103 if (n_tokens != 8) {
4104 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4108 pipeline_name = tokens[1];
4110 if (strcmp(tokens[2], "table") != 0) {
4111 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
4115 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4116 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4120 if (strcmp(tokens[4], "rule") != 0) {
4121 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
4125 if (strcmp(tokens[5], "delete") != 0) {
4126 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4130 if (strcmp(tokens[6], "match") != 0) {
4131 snprintf(out, out_size, MSG_ARG_INVALID, "match");
4135 if (strcmp(tokens[7], "default") != 0) {
4136 snprintf(out, out_size, MSG_ARG_INVALID, "default");
4140 status = pipeline_table_rule_delete_default(pipeline_name,
4143 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4149 static const char cmd_pipeline_table_rule_stats_read_help[] =
4150 "pipeline <pipeline_name> table <table_id> rule read stats [clear]\n";
4153 cmd_pipeline_table_rule_stats_read(char **tokens,
4154 uint32_t n_tokens __rte_unused,
4158 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
4162 static const char cmd_pipeline_table_meter_profile_add_help[] =
4163 "pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n"
4164 " add srtcm cir <cir> cbs <cbs> ebs <ebs>\n"
4165 " | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n";
4168 cmd_pipeline_table_meter_profile_add(char **tokens,
4173 struct rte_table_action_meter_profile p;
4174 char *pipeline_name;
4175 uint32_t table_id, meter_profile_id;
4179 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4183 pipeline_name = tokens[1];
4185 if (strcmp(tokens[2], "table") != 0) {
4186 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
4190 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4191 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4195 if (strcmp(tokens[4], "meter") != 0) {
4196 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
4200 if (strcmp(tokens[5], "profile") != 0) {
4201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
4205 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
4206 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
4210 if (strcmp(tokens[7], "add") != 0) {
4211 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
4215 if (strcmp(tokens[8], "srtcm") == 0) {
4216 if (n_tokens != 15) {
4217 snprintf(out, out_size, MSG_ARG_MISMATCH,
4222 p.alg = RTE_TABLE_ACTION_METER_SRTCM;
4224 if (strcmp(tokens[9], "cir") != 0) {
4225 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
4229 if (parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
4230 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
4234 if (strcmp(tokens[11], "cbs") != 0) {
4235 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
4239 if (parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
4240 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
4244 if (strcmp(tokens[13], "ebs") != 0) {
4245 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
4249 if (parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
4250 snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
4253 } else if (strcmp(tokens[8], "trtcm") == 0) {
4254 if (n_tokens != 17) {
4255 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4259 p.alg = RTE_TABLE_ACTION_METER_TRTCM;
4261 if (strcmp(tokens[9], "cir") != 0) {
4262 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
4266 if (parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
4267 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
4271 if (strcmp(tokens[11], "pir") != 0) {
4272 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
4276 if (parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
4277 snprintf(out, out_size, MSG_ARG_INVALID, "pir");
4280 if (strcmp(tokens[13], "cbs") != 0) {
4281 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
4285 if (parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
4286 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
4290 if (strcmp(tokens[15], "pbs") != 0) {
4291 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
4295 if (parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
4296 snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
4300 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4304 status = pipeline_table_mtr_profile_add(pipeline_name,
4309 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4315 static const char cmd_pipeline_table_meter_profile_delete_help[] =
4316 "pipeline <pipeline_name> table <table_id>\n"
4317 " meter profile <meter_profile_id> delete\n";
4320 cmd_pipeline_table_meter_profile_delete(char **tokens,
4325 char *pipeline_name;
4326 uint32_t table_id, meter_profile_id;
4329 if (n_tokens != 8) {
4330 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4334 pipeline_name = tokens[1];
4336 if (strcmp(tokens[2], "table") != 0) {
4337 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
4341 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4342 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4346 if (strcmp(tokens[4], "meter") != 0) {
4347 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
4351 if (strcmp(tokens[5], "profile") != 0) {
4352 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
4356 if (parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
4357 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
4361 if (strcmp(tokens[7], "delete") != 0) {
4362 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4366 status = pipeline_table_mtr_profile_delete(pipeline_name,
4370 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4376 static const char cmd_pipeline_table_rule_meter_read_help[] =
4377 "pipeline <pipeline_name> table <table_id> rule read meter [clear]\n";
4380 cmd_pipeline_table_rule_meter_read(char **tokens,
4381 uint32_t n_tokens __rte_unused,
4385 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
4389 static const char cmd_pipeline_table_dscp_help[] =
4390 "pipeline <pipeline_name> table <table_id> dscp <file_name>\n"
4392 " File <file_name>:\n"
4393 " - exactly 64 lines\n"
4394 " - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n";
4397 load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
4398 const char *file_name,
4399 uint32_t *line_number)
4404 /* Check input arguments */
4405 if ((dscp_table == NULL) ||
4406 (file_name == NULL) ||
4407 (line_number == NULL)) {
4413 /* Open input file */
4414 f = fopen(file_name, "r");
4421 for (dscp = 0, l = 1; ; l++) {
4424 enum rte_meter_color color;
4425 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
4427 if (fgets(line, sizeof(line), f) == NULL)
4430 if (is_comment(line))
4433 if (parse_tokenize_string(line, tokens, &n_tokens)) {
4442 if ((dscp >= RTE_DIM(dscp_table->entry)) ||
4443 (n_tokens != RTE_DIM(tokens)) ||
4444 parser_read_uint32(&tc_id, tokens[0]) ||
4445 (tc_id >= RTE_TABLE_ACTION_TC_MAX) ||
4446 parser_read_uint32(&tc_queue_id, tokens[1]) ||
4447 (tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX) ||
4448 (strlen(tokens[2]) != 1)) {
4454 switch (tokens[2][0]) {
4457 color = e_RTE_METER_GREEN;
4462 color = e_RTE_METER_YELLOW;
4467 color = e_RTE_METER_RED;
4476 dscp_table->entry[dscp].tc_id = tc_id;
4477 dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
4478 dscp_table->entry[dscp].color = color;
4488 cmd_pipeline_table_dscp(char **tokens,
4493 struct rte_table_action_dscp_table dscp_table;
4494 char *pipeline_name, *file_name;
4495 uint32_t table_id, line_number;
4498 if (n_tokens != 6) {
4499 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4503 pipeline_name = tokens[1];
4505 if (strcmp(tokens[2], "table") != 0) {
4506 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
4510 if (parser_read_uint32(&table_id, tokens[3]) != 0) {
4511 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4515 if (strcmp(tokens[4], "dscp") != 0) {
4516 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
4520 file_name = tokens[5];
4522 status = load_dscp_table(&dscp_table, file_name, &line_number);
4524 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
4528 status = pipeline_table_dscp_table_update(pipeline_name,
4533 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4539 static const char cmd_pipeline_table_rule_ttl_read_help[] =
4540 "pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n";
4543 cmd_pipeline_table_rule_ttl_read(char **tokens,
4544 uint32_t n_tokens __rte_unused,
4548 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
4552 static const char cmd_thread_pipeline_enable_help[] =
4553 "thread <thread_id> pipeline <pipeline_name> enable\n";
4556 cmd_thread_pipeline_enable(char **tokens,
4561 char *pipeline_name;
4565 if (n_tokens != 5) {
4566 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4570 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
4571 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
4575 if (strcmp(tokens[2], "pipeline") != 0) {
4576 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
4580 pipeline_name = tokens[3];
4582 if (strcmp(tokens[4], "enable") != 0) {
4583 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
4587 status = thread_pipeline_enable(thread_id, pipeline_name);
4589 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
4595 static const char cmd_thread_pipeline_disable_help[] =
4596 "thread <thread_id> pipeline <pipeline_name> disable\n";
4599 cmd_thread_pipeline_disable(char **tokens,
4604 char *pipeline_name;
4608 if (n_tokens != 5) {
4609 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4613 if (parser_read_uint32(&thread_id, tokens[1]) != 0) {
4614 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
4618 if (strcmp(tokens[2], "pipeline") != 0) {
4619 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
4623 pipeline_name = tokens[3];
4625 if (strcmp(tokens[4], "disable") != 0) {
4626 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
4630 status = thread_pipeline_disable(thread_id, pipeline_name);
4632 snprintf(out, out_size, MSG_CMD_FAIL,
4633 "thread pipeline disable");
4639 cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size)
4644 if (n_tokens == 0) {
4645 snprintf(out, out_size,
4646 "Type 'help <command>' for details on each command.\n\n"
4647 "List of commands:\n"
4651 "\ttmgr subport profile\n"
4652 "\ttmgr pipe profile\n"
4655 "\ttmgr subport pipe\n"
4658 "\tport in action profile\n"
4659 "\ttable action profile\n"
4661 "\tpipeline port in\n"
4662 "\tpipeline port out\n"
4663 "\tpipeline table\n"
4664 "\tpipeline port in table\n"
4665 "\tpipeline port in stats\n"
4666 "\tpipeline port in enable\n"
4667 "\tpipeline port in disable\n"
4668 "\tpipeline port out stats\n"
4669 "\tpipeline table stats\n"
4670 "\tpipeline table rule add\n"
4671 "\tpipeline table rule add default\n"
4672 "\tpipeline table rule add bulk\n"
4673 "\tpipeline table rule delete\n"
4674 "\tpipeline table rule delete default\n"
4675 "\tpipeline table rule stats read\n"
4676 "\tpipeline table meter profile add\n"
4677 "\tpipeline table meter profile delete\n"
4678 "\tpipeline table rule meter read\n"
4679 "\tpipeline table dscp\n"
4680 "\tpipeline table rule ttl read\n"
4681 "\tthread pipeline enable\n"
4682 "\tthread pipeline disable\n\n");
4686 if (strcmp(tokens[0], "mempool") == 0) {
4687 snprintf(out, out_size, "\n%s\n", cmd_mempool_help);
4691 if (strcmp(tokens[0], "link") == 0) {
4692 snprintf(out, out_size, "\n%s\n", cmd_link_help);
4696 if (strcmp(tokens[0], "swq") == 0) {
4697 snprintf(out, out_size, "\n%s\n", cmd_swq_help);
4701 if (strcmp(tokens[0], "tmgr") == 0) {
4702 if (n_tokens == 1) {
4703 snprintf(out, out_size, "\n%s\n", cmd_tmgr_help);
4707 if ((n_tokens == 2) &&
4708 (strcmp(tokens[1], "subport")) == 0) {
4709 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help);
4713 if ((n_tokens == 3) &&
4714 (strcmp(tokens[1], "subport") == 0) &&
4715 (strcmp(tokens[2], "profile") == 0)) {
4716 snprintf(out, out_size, "\n%s\n",
4717 cmd_tmgr_subport_profile_help);
4721 if ((n_tokens == 3) &&
4722 (strcmp(tokens[1], "subport") == 0) &&
4723 (strcmp(tokens[2], "pipe") == 0)) {
4724 snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help);
4728 if ((n_tokens == 3) &&
4729 (strcmp(tokens[1], "pipe") == 0) &&
4730 (strcmp(tokens[2], "profile") == 0)) {
4731 snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help);
4736 if (strcmp(tokens[0], "tap") == 0) {
4737 snprintf(out, out_size, "\n%s\n", cmd_tap_help);
4741 if (strcmp(tokens[0], "kni") == 0) {
4742 snprintf(out, out_size, "\n%s\n", cmd_kni_help);
4746 if ((n_tokens == 4) &&
4747 (strcmp(tokens[0], "port") == 0) &&
4748 (strcmp(tokens[1], "in") == 0) &&
4749 (strcmp(tokens[2], "action") == 0) &&
4750 (strcmp(tokens[3], "profile") == 0)) {
4751 snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help);
4755 if ((n_tokens == 3) &&
4756 (strcmp(tokens[0], "table") == 0) &&
4757 (strcmp(tokens[1], "action") == 0) &&
4758 (strcmp(tokens[2], "profile") == 0)) {
4759 snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help);
4763 if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) {
4764 snprintf(out, out_size, "\n%s\n", cmd_pipeline_help);
4768 if ((strcmp(tokens[0], "pipeline") == 0) &&
4769 (strcmp(tokens[1], "port") == 0)) {
4770 if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) {
4771 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help);
4775 if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) {
4776 snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help);
4780 if ((n_tokens == 4) &&
4781 (strcmp(tokens[2], "in") == 0) &&
4782 (strcmp(tokens[3], "table") == 0)) {
4783 snprintf(out, out_size, "\n%s\n",
4784 cmd_pipeline_port_in_table_help);
4788 if ((n_tokens == 4) &&
4789 (strcmp(tokens[2], "in") == 0) &&
4790 (strcmp(tokens[3], "stats") == 0)) {
4791 snprintf(out, out_size, "\n%s\n",
4792 cmd_pipeline_port_in_stats_help);
4796 if ((n_tokens == 4) &&
4797 (strcmp(tokens[2], "in") == 0) &&
4798 (strcmp(tokens[3], "enable") == 0)) {
4799 snprintf(out, out_size, "\n%s\n",
4800 cmd_pipeline_port_in_enable_help);
4804 if ((n_tokens == 4) &&
4805 (strcmp(tokens[2], "in") == 0) &&
4806 (strcmp(tokens[3], "disable") == 0)) {
4807 snprintf(out, out_size, "\n%s\n",
4808 cmd_pipeline_port_in_disable_help);
4812 if ((n_tokens == 4) &&
4813 (strcmp(tokens[2], "out") == 0) &&
4814 (strcmp(tokens[3], "stats") == 0)) {
4815 snprintf(out, out_size, "\n%s\n",
4816 cmd_pipeline_port_out_stats_help);
4821 if ((strcmp(tokens[0], "pipeline") == 0) &&
4822 (strcmp(tokens[1], "table") == 0)) {
4823 if (n_tokens == 2) {
4824 snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help);
4828 if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) {
4829 snprintf(out, out_size, "\n%s\n",
4830 cmd_pipeline_table_stats_help);
4834 if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) {
4835 snprintf(out, out_size, "\n%s\n",
4836 cmd_pipeline_table_dscp_help);
4840 if ((n_tokens == 4) &&
4841 (strcmp(tokens[2], "rule") == 0) &&
4842 (strcmp(tokens[3], "add") == 0)) {
4843 snprintf(out, out_size, "\n%s\n",
4844 cmd_pipeline_table_rule_add_help);
4848 if ((n_tokens == 5) &&
4849 (strcmp(tokens[2], "rule") == 0) &&
4850 (strcmp(tokens[3], "add") == 0) &&
4851 (strcmp(tokens[4], "default") == 0)) {
4852 snprintf(out, out_size, "\n%s\n",
4853 cmd_pipeline_table_rule_add_default_help);
4857 if ((n_tokens == 5) &&
4858 (strcmp(tokens[2], "rule") == 0) &&
4859 (strcmp(tokens[3], "add") == 0) &&
4860 (strcmp(tokens[4], "bulk") == 0)) {
4861 snprintf(out, out_size, "\n%s\n",
4862 cmd_pipeline_table_rule_add_bulk_help);
4866 if ((n_tokens == 4) &&
4867 (strcmp(tokens[2], "rule") == 0) &&
4868 (strcmp(tokens[3], "delete") == 0)) {
4869 snprintf(out, out_size, "\n%s\n",
4870 cmd_pipeline_table_rule_delete_help);
4874 if ((n_tokens == 5) &&
4875 (strcmp(tokens[2], "rule") == 0) &&
4876 (strcmp(tokens[3], "delete") == 0) &&
4877 (strcmp(tokens[4], "default") == 0)) {
4878 snprintf(out, out_size, "\n%s\n",
4879 cmd_pipeline_table_rule_delete_default_help);
4883 if ((n_tokens == 5) &&
4884 (strcmp(tokens[2], "rule") == 0) &&
4885 (strcmp(tokens[3], "stats") == 0) &&
4886 (strcmp(tokens[4], "read") == 0)) {
4887 snprintf(out, out_size, "\n%s\n",
4888 cmd_pipeline_table_rule_stats_read_help);
4892 if ((n_tokens == 5) &&
4893 (strcmp(tokens[2], "meter") == 0) &&
4894 (strcmp(tokens[3], "profile") == 0) &&
4895 (strcmp(tokens[4], "add") == 0)) {
4896 snprintf(out, out_size, "\n%s\n",
4897 cmd_pipeline_table_meter_profile_add_help);
4901 if ((n_tokens == 5) &&
4902 (strcmp(tokens[2], "meter") == 0) &&
4903 (strcmp(tokens[3], "profile") == 0) &&
4904 (strcmp(tokens[4], "delete") == 0)) {
4905 snprintf(out, out_size, "\n%s\n",
4906 cmd_pipeline_table_meter_profile_delete_help);
4910 if ((n_tokens == 5) &&
4911 (strcmp(tokens[2], "rule") == 0) &&
4912 (strcmp(tokens[3], "meter") == 0) &&
4913 (strcmp(tokens[4], "read") == 0)) {
4914 snprintf(out, out_size, "\n%s\n",
4915 cmd_pipeline_table_rule_meter_read_help);
4919 if ((n_tokens == 5) &&
4920 (strcmp(tokens[2], "rule") == 0) &&
4921 (strcmp(tokens[3], "ttl") == 0) &&
4922 (strcmp(tokens[4], "read") == 0)) {
4923 snprintf(out, out_size, "\n%s\n",
4924 cmd_pipeline_table_rule_ttl_read_help);
4929 if ((n_tokens == 3) &&
4930 (strcmp(tokens[0], "thread") == 0) &&
4931 (strcmp(tokens[1], "pipeline") == 0)) {
4932 if (strcmp(tokens[2], "enable") == 0) {
4933 snprintf(out, out_size, "\n%s\n",
4934 cmd_thread_pipeline_enable_help);
4938 if (strcmp(tokens[2], "disable") == 0) {
4939 snprintf(out, out_size, "\n%s\n",
4940 cmd_thread_pipeline_disable_help);
4945 snprintf(out, out_size, "Invalid command\n");
4949 cli_process(char *in, char *out, size_t out_size)
4951 char *tokens[CMD_MAX_TOKENS];
4952 uint32_t n_tokens = RTE_DIM(tokens);
4958 status = parse_tokenize_string(in, tokens, &n_tokens);
4960 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
4967 if (strcmp(tokens[0], "help") == 0) {
4968 cmd_help(tokens, n_tokens, out, out_size);
4972 if (strcmp(tokens[0], "mempool") == 0) {
4973 cmd_mempool(tokens, n_tokens, out, out_size);
4977 if (strcmp(tokens[0], "link") == 0) {
4978 if (strcmp(tokens[1], "show") == 0) {
4979 cmd_link_show(tokens, n_tokens, out, out_size);
4983 cmd_link(tokens, n_tokens, out, out_size);
4987 if (strcmp(tokens[0], "swq") == 0) {
4988 cmd_swq(tokens, n_tokens, out, out_size);
4992 if (strcmp(tokens[0], "tmgr") == 0) {
4993 if ((n_tokens >= 3) &&
4994 (strcmp(tokens[1], "subport") == 0) &&
4995 (strcmp(tokens[2], "profile") == 0)) {
4996 cmd_tmgr_subport_profile(tokens, n_tokens,
5001 if ((n_tokens >= 3) &&
5002 (strcmp(tokens[1], "pipe") == 0) &&
5003 (strcmp(tokens[2], "profile") == 0)) {
5004 cmd_tmgr_pipe_profile(tokens, n_tokens, out, out_size);
5008 if ((n_tokens >= 5) &&
5009 (strcmp(tokens[2], "subport") == 0) &&
5010 (strcmp(tokens[4], "profile") == 0)) {
5011 cmd_tmgr_subport(tokens, n_tokens, out, out_size);
5015 if ((n_tokens >= 5) &&
5016 (strcmp(tokens[2], "subport") == 0) &&
5017 (strcmp(tokens[4], "pipe") == 0)) {
5018 cmd_tmgr_subport_pipe(tokens, n_tokens, out, out_size);
5022 cmd_tmgr(tokens, n_tokens, out, out_size);
5026 if (strcmp(tokens[0], "tap") == 0) {
5027 cmd_tap(tokens, n_tokens, out, out_size);
5031 if (strcmp(tokens[0], "kni") == 0) {
5032 cmd_kni(tokens, n_tokens, out, out_size);
5036 if (strcmp(tokens[0], "port") == 0) {
5037 cmd_port_in_action_profile(tokens, n_tokens, out, out_size);
5041 if (strcmp(tokens[0], "table") == 0) {
5042 cmd_table_action_profile(tokens, n_tokens, out, out_size);
5046 if (strcmp(tokens[0], "pipeline") == 0) {
5047 if ((n_tokens >= 3) &&
5048 (strcmp(tokens[2], "period") == 0)) {
5049 cmd_pipeline(tokens, n_tokens, out, out_size);
5053 if ((n_tokens >= 5) &&
5054 (strcmp(tokens[2], "port") == 0) &&
5055 (strcmp(tokens[3], "in") == 0) &&
5056 (strcmp(tokens[4], "bsz") == 0)) {
5057 cmd_pipeline_port_in(tokens, n_tokens, out, out_size);
5061 if ((n_tokens >= 5) &&
5062 (strcmp(tokens[2], "port") == 0) &&
5063 (strcmp(tokens[3], "out") == 0) &&
5064 (strcmp(tokens[4], "bsz") == 0)) {
5065 cmd_pipeline_port_out(tokens, n_tokens, out, out_size);
5069 if ((n_tokens >= 4) &&
5070 (strcmp(tokens[2], "table") == 0) &&
5071 (strcmp(tokens[3], "match") == 0)) {
5072 cmd_pipeline_table(tokens, n_tokens, out, out_size);
5076 if ((n_tokens >= 6) &&
5077 (strcmp(tokens[2], "port") == 0) &&
5078 (strcmp(tokens[3], "in") == 0) &&
5079 (strcmp(tokens[5], "table") == 0)) {
5080 cmd_pipeline_port_in_table(tokens, n_tokens,
5085 if ((n_tokens >= 6) &&
5086 (strcmp(tokens[2], "port") == 0) &&
5087 (strcmp(tokens[3], "in") == 0) &&
5088 (strcmp(tokens[5], "stats") == 0)) {
5089 cmd_pipeline_port_in_stats(tokens, n_tokens,
5094 if ((n_tokens >= 6) &&
5095 (strcmp(tokens[2], "port") == 0) &&
5096 (strcmp(tokens[3], "in") == 0) &&
5097 (strcmp(tokens[5], "enable") == 0)) {
5098 cmd_pipeline_port_in_enable(tokens, n_tokens,
5103 if ((n_tokens >= 6) &&
5104 (strcmp(tokens[2], "port") == 0) &&
5105 (strcmp(tokens[3], "in") == 0) &&
5106 (strcmp(tokens[5], "disable") == 0)) {
5107 cmd_pipeline_port_in_disable(tokens, n_tokens,
5112 if ((n_tokens >= 6) &&
5113 (strcmp(tokens[2], "port") == 0) &&
5114 (strcmp(tokens[3], "out") == 0) &&
5115 (strcmp(tokens[5], "stats") == 0)) {
5116 cmd_pipeline_port_out_stats(tokens, n_tokens,
5121 if ((n_tokens >= 5) &&
5122 (strcmp(tokens[2], "table") == 0) &&
5123 (strcmp(tokens[4], "stats") == 0)) {
5124 cmd_pipeline_table_stats(tokens, n_tokens,
5129 if ((n_tokens >= 7) &&
5130 (strcmp(tokens[2], "table") == 0) &&
5131 (strcmp(tokens[4], "rule") == 0) &&
5132 (strcmp(tokens[5], "add") == 0) &&
5133 (strcmp(tokens[6], "match") == 0)) {
5134 if ((n_tokens >= 8) &&
5135 (strcmp(tokens[7], "default") == 0)) {
5136 cmd_pipeline_table_rule_add_default(tokens,
5137 n_tokens, out, out_size);
5141 cmd_pipeline_table_rule_add(tokens, n_tokens,
5146 if ((n_tokens >= 7) &&
5147 (strcmp(tokens[2], "table") == 0) &&
5148 (strcmp(tokens[4], "rule") == 0) &&
5149 (strcmp(tokens[5], "add") == 0) &&
5150 (strcmp(tokens[6], "bulk") == 0)) {
5151 cmd_pipeline_table_rule_add_bulk(tokens,
5152 n_tokens, out, out_size);
5156 if ((n_tokens >= 7) &&
5157 (strcmp(tokens[2], "table") == 0) &&
5158 (strcmp(tokens[4], "rule") == 0) &&
5159 (strcmp(tokens[5], "delete") == 0) &&
5160 (strcmp(tokens[6], "match") == 0)) {
5161 if ((n_tokens >= 8) &&
5162 (strcmp(tokens[7], "default") == 0)) {
5163 cmd_pipeline_table_rule_delete_default(tokens,
5164 n_tokens, out, out_size);
5168 cmd_pipeline_table_rule_delete(tokens, n_tokens,
5173 if ((n_tokens >= 7) &&
5174 (strcmp(tokens[2], "table") == 0) &&
5175 (strcmp(tokens[4], "rule") == 0) &&
5176 (strcmp(tokens[5], "read") == 0) &&
5177 (strcmp(tokens[6], "stats") == 0)) {
5178 cmd_pipeline_table_rule_stats_read(tokens, n_tokens,
5183 if ((n_tokens >= 8) &&
5184 (strcmp(tokens[2], "table") == 0) &&
5185 (strcmp(tokens[4], "meter") == 0) &&
5186 (strcmp(tokens[5], "profile") == 0) &&
5187 (strcmp(tokens[7], "add") == 0)) {
5188 cmd_pipeline_table_meter_profile_add(tokens, n_tokens,
5193 if ((n_tokens >= 8) &&
5194 (strcmp(tokens[2], "table") == 0) &&
5195 (strcmp(tokens[4], "meter") == 0) &&
5196 (strcmp(tokens[5], "profile") == 0) &&
5197 (strcmp(tokens[7], "delete") == 0)) {
5198 cmd_pipeline_table_meter_profile_delete(tokens,
5199 n_tokens, out, out_size);
5203 if ((n_tokens >= 7) &&
5204 (strcmp(tokens[2], "table") == 0) &&
5205 (strcmp(tokens[4], "rule") == 0) &&
5206 (strcmp(tokens[5], "read") == 0) &&
5207 (strcmp(tokens[6], "meter") == 0)) {
5208 cmd_pipeline_table_rule_meter_read(tokens, n_tokens,
5213 if ((n_tokens >= 5) &&
5214 (strcmp(tokens[2], "table") == 0) &&
5215 (strcmp(tokens[4], "dscp") == 0)) {
5216 cmd_pipeline_table_dscp(tokens, n_tokens,
5221 if ((n_tokens >= 7) &&
5222 (strcmp(tokens[2], "table") == 0) &&
5223 (strcmp(tokens[4], "rule") == 0) &&
5224 (strcmp(tokens[5], "read") == 0) &&
5225 (strcmp(tokens[6], "ttl") == 0)) {
5226 cmd_pipeline_table_rule_ttl_read(tokens, n_tokens,
5232 if (strcmp(tokens[0], "thread") == 0) {
5233 if ((n_tokens >= 5) &&
5234 (strcmp(tokens[4], "enable") == 0)) {
5235 cmd_thread_pipeline_enable(tokens, n_tokens,
5240 if ((n_tokens >= 5) &&
5241 (strcmp(tokens[4], "disable") == 0)) {
5242 cmd_thread_pipeline_disable(tokens, n_tokens,
5248 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
5252 cli_script_process(const char *file_name,
5253 size_t msg_in_len_max,
5254 size_t msg_out_len_max)
5256 char *msg_in = NULL, *msg_out = NULL;
5259 /* Check input arguments */
5260 if ((file_name == NULL) ||
5261 (strlen(file_name) == 0) ||
5262 (msg_in_len_max == 0) ||
5263 (msg_out_len_max == 0))
5266 msg_in = malloc(msg_in_len_max + 1);
5267 msg_out = malloc(msg_out_len_max + 1);
5268 if ((msg_in == NULL) ||
5269 (msg_out == NULL)) {
5275 /* Open input file */
5276 f = fopen(file_name, "r");
5285 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
5288 printf("%s", msg_in);
5295 if (strlen(msg_out))
5296 printf("%s", msg_out);
5307 cli_rule_file_process(const char *file_name,
5308 size_t line_len_max,
5309 struct table_rule_match *m,
5310 struct table_rule_action *a,
5312 uint32_t *line_number,
5318 uint32_t rule_id, line_id;
5321 /* Check input arguments */
5322 if ((file_name == NULL) ||
5323 (strlen(file_name) == 0) ||
5324 (line_len_max == 0)) {
5329 /* Memory allocation */
5330 line = malloc(line_len_max + 1);
5337 f = fopen(file_name, "r");
5345 for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
5346 char *tokens[CMD_MAX_TOKENS];
5347 uint32_t n_tokens, n_tokens_parsed, t0;
5349 /* Read next line from file. */
5350 if (fgets(line, line_len_max + 1, f) == NULL)
5354 if (is_comment(line))
5358 n_tokens = RTE_DIM(tokens);
5359 status = parse_tokenize_string(line, tokens, &n_tokens);
5371 n_tokens_parsed = parse_match(tokens + t0,
5376 if (n_tokens_parsed == 0) {
5380 t0 += n_tokens_parsed;
5383 n_tokens_parsed = parse_table_action(tokens + t0,
5388 if (n_tokens_parsed == 0) {
5392 t0 += n_tokens_parsed;
5394 /* Line completed. */
5395 if (t0 < n_tokens) {
5400 /* Increment rule count */
5411 *line_number = line_id;