1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2018 Intel Corporation
10 #include <rte_common.h>
11 #include <rte_cycles.h>
13 #include "rte_eth_softnic_internals.h"
16 #ifndef CMD_MAX_TOKENS
17 #define CMD_MAX_TOKENS 256
20 #define MSG_OUT_OF_MEMORY "Not enough memory.\n"
21 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n"
22 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n"
23 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n"
24 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n"
25 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n"
26 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n"
27 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n"
28 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n"
29 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n"
30 #define MSG_CMD_FAIL "Command \"%s\" failed.\n"
35 if ((strlen(in) && index("!#%;", in[0])) ||
36 (strncmp(in, "//", 2) == 0) ||
37 (strncmp(in, "--", 2) == 0))
44 * mempool <mempool_name>
45 * buffer <buffer_size>
50 cmd_mempool(struct pmd_internals *softnic,
56 struct softnic_mempool_params p;
58 struct softnic_mempool *mempool;
61 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
67 if (strcmp(tokens[2], "buffer") != 0) {
68 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer");
72 if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) {
73 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size");
77 if (strcmp(tokens[4], "pool") != 0) {
78 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool");
82 if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) {
83 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size");
87 if (strcmp(tokens[6], "cache") != 0) {
88 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache");
92 if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) {
93 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size");
97 mempool = softnic_mempool_create(softnic, name, &p);
98 if (mempool == NULL) {
99 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
106 * dev <device_name> | port <port_id>
109 cmd_link(struct pmd_internals *softnic,
115 struct softnic_link_params p;
116 struct softnic_link *link;
119 memset(&p, 0, sizeof(p));
122 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
127 if (strcmp(tokens[2], "dev") == 0) {
128 p.dev_name = tokens[3];
129 } else if (strcmp(tokens[2], "port") == 0) {
132 if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) {
133 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
137 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port");
141 link = softnic_link_create(softnic, name, &p);
143 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
153 cmd_swq(struct pmd_internals *softnic,
159 struct softnic_swq_params p;
161 struct softnic_swq *swq;
164 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
170 if (strcmp(tokens[2], "size") != 0) {
171 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
175 if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) {
176 snprintf(out, out_size, MSG_ARG_INVALID, "size");
180 swq = softnic_swq_create(softnic, name, &p);
182 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
188 * tmgr shaper profile
190 * rate <tb_rate> size <tb_size>
191 * adj <packet_length_adjust>
194 cmd_tmgr_shaper_profile(struct pmd_internals *softnic,
200 struct rte_tm_shaper_params sp;
201 struct rte_tm_error error;
202 uint32_t shaper_profile_id;
206 memset(&sp, 0, sizeof(struct rte_tm_shaper_params));
208 if (n_tokens != 11) {
209 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
213 if (strcmp(tokens[1], "shaper") != 0) {
214 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
218 if (strcmp(tokens[2], "profile") != 0) {
219 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
223 if (strcmp(tokens[3], "id") != 0) {
224 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
228 if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) {
229 snprintf(out, out_size, MSG_ARG_INVALID, "profile_id");
233 if (strcmp(tokens[5], "rate") != 0) {
234 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate");
238 if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) {
239 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate");
243 if (strcmp(tokens[7], "size") != 0) {
244 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
248 if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) {
249 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size");
253 if (strcmp(tokens[9], "adj") != 0) {
254 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj");
258 if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) {
259 snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust");
263 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
267 status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error);
269 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
276 * id <shared_shaper_id>
277 * profile <shaper_profile_id>
280 cmd_tmgr_shared_shaper(struct pmd_internals *softnic,
286 struct rte_tm_error error;
287 uint32_t shared_shaper_id, shaper_profile_id;
292 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
296 if (strcmp(tokens[1], "shared") != 0) {
297 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared");
301 if (strcmp(tokens[2], "shaper") != 0) {
302 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper");
306 if (strcmp(tokens[3], "id") != 0) {
307 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
311 if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) {
312 snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
316 if (strcmp(tokens[5], "profile") != 0) {
317 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
321 if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) {
322 snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
326 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
330 status = rte_tm_shared_shaper_add_update(port_id,
335 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
343 * parent <parent_node_id | none>
344 * priority <priority>
346 * [shaper profile <shaper_profile_id>]
347 * [shared shaper <shared_shaper_id>]
348 * [nonleaf sp <n_sp_priorities>]
351 cmd_tmgr_node(struct pmd_internals *softnic,
357 struct rte_tm_error error;
358 struct rte_tm_node_params np;
359 uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id;
363 memset(&np, 0, sizeof(struct rte_tm_node_params));
364 np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
365 np.nonleaf.n_sp_priorities = 1;
368 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
372 if (strcmp(tokens[1], "node") != 0) {
373 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node");
377 if (strcmp(tokens[2], "id") != 0) {
378 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id");
382 if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) {
383 snprintf(out, out_size, MSG_ARG_INVALID, "node_id");
387 if (strcmp(tokens[4], "parent") != 0) {
388 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent");
392 if (strcmp(tokens[5], "none") == 0)
393 parent_node_id = RTE_TM_NODE_ID_NULL;
395 if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) {
396 snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id");
401 if (strcmp(tokens[6], "priority") != 0) {
402 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
406 if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) {
407 snprintf(out, out_size, MSG_ARG_INVALID, "priority");
411 if (strcmp(tokens[8], "weight") != 0) {
412 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight");
416 if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) {
417 snprintf(out, out_size, MSG_ARG_INVALID, "weight");
425 (strcmp(tokens[0], "shaper") == 0) &&
426 (strcmp(tokens[1], "profile") == 0)) {
428 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
432 if (strcmp(tokens[2], "none") == 0) {
433 np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE;
435 if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) {
436 snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id");
443 } /* shaper profile */
446 (strcmp(tokens[0], "shared") == 0) &&
447 (strcmp(tokens[1], "shaper") == 0)) {
449 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
453 if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) {
454 snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id");
458 np.shared_shaper_id = &shared_shaper_id;
459 np.n_shared_shapers = 1;
463 } /* shared shaper */
466 (strcmp(tokens[0], "nonleaf") == 0) &&
467 (strcmp(tokens[1], "sp") == 0)) {
469 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node");
473 if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) {
474 snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities");
480 } /* nonleaf sp <n_sp_priorities> */
483 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
487 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
491 status = rte_tm_node_add(port_id,
496 RTE_TM_NODE_LEVEL_ID_ANY,
500 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
506 * tmgr hierarchy commit
509 cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic,
515 struct rte_tm_error error;
520 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
524 if (strcmp(tokens[1], "hierarchy") != 0) {
525 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy");
529 if (strcmp(tokens[2], "commit") != 0) {
530 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit");
534 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id);
538 status = rte_tm_hierarchy_commit(port_id, 1, &error);
540 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
549 cmd_tmgr(struct pmd_internals *softnic,
556 struct softnic_tmgr_port *tmgr_port;
559 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
565 tmgr_port = softnic_tmgr_port_create(softnic, name);
566 if (tmgr_port == NULL) {
567 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
576 cmd_tap(struct pmd_internals *softnic,
583 struct softnic_tap *tap;
586 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
592 tap = softnic_tap_create(softnic, name);
594 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
600 * port in action profile <profile_name>
601 * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]
602 * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]
605 cmd_port_in_action_profile(struct pmd_internals *softnic,
611 struct softnic_port_in_action_profile_params p;
612 struct softnic_port_in_action_profile *ap;
616 memset(&p, 0, sizeof(p));
619 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
623 if (strcmp(tokens[1], "in") != 0) {
624 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
628 if (strcmp(tokens[2], "action") != 0) {
629 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
633 if (strcmp(tokens[3], "profile") != 0) {
634 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
643 (strcmp(tokens[t0], "filter") == 0)) {
646 if (n_tokens < t0 + 10) {
647 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter");
651 if (strcmp(tokens[t0 + 1], "match") == 0) {
652 p.fltr.filter_on_match = 1;
653 } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) {
654 p.fltr.filter_on_match = 0;
656 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch");
660 if (strcmp(tokens[t0 + 2], "offset") != 0) {
661 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
665 if (softnic_parser_read_uint32(&p.fltr.key_offset,
666 tokens[t0 + 3]) != 0) {
667 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
671 if (strcmp(tokens[t0 + 4], "mask") != 0) {
672 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
676 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
677 if ((softnic_parse_hex_string(tokens[t0 + 5],
678 p.fltr.key_mask, &size) != 0) ||
679 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
680 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
684 if (strcmp(tokens[t0 + 6], "key") != 0) {
685 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
689 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE;
690 if ((softnic_parse_hex_string(tokens[t0 + 7],
691 p.fltr.key, &size) != 0) ||
692 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) {
693 snprintf(out, out_size, MSG_ARG_INVALID, "key_value");
697 if (strcmp(tokens[t0 + 8], "port") != 0) {
698 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
702 if (softnic_parser_read_uint32(&p.fltr.port_id,
703 tokens[t0 + 9]) != 0) {
704 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
708 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR;
713 (strcmp(tokens[t0], "balance") == 0)) {
716 if (n_tokens < t0 + 22) {
717 snprintf(out, out_size, MSG_ARG_MISMATCH,
718 "port in action profile balance");
722 if (strcmp(tokens[t0 + 1], "offset") != 0) {
723 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
727 if (softnic_parser_read_uint32(&p.lb.key_offset,
728 tokens[t0 + 2]) != 0) {
729 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
733 if (strcmp(tokens[t0 + 3], "mask") != 0) {
734 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
738 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
739 if (softnic_parse_hex_string(tokens[t0 + 4],
740 p.lb.key_mask, &p.lb.key_size) != 0) {
741 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
745 if (strcmp(tokens[t0 + 5], "port") != 0) {
746 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
750 for (i = 0; i < 16; i++)
751 if (softnic_parser_read_uint32(&p.lb.port_id[i],
752 tokens[t0 + 6 + i]) != 0) {
753 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
757 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB;
762 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
766 ap = softnic_port_in_action_profile_create(softnic, name, &p);
768 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
774 * table action profile <profile_name>
778 * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]
779 * [meter srtcm | trtcm
781 * stats none | pkts | bytes | both]
782 * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]
783 * [encap ether | vlan | qinq | mpls | pppoe]
788 * [stats pkts | bytes | both]
792 cmd_table_action_profile(struct pmd_internals *softnic,
798 struct softnic_table_action_profile_params p;
799 struct softnic_table_action_profile *ap;
803 memset(&p, 0, sizeof(p));
806 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
810 if (strcmp(tokens[1], "action") != 0) {
811 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action");
815 if (strcmp(tokens[2], "profile") != 0) {
816 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
822 if (strcmp(tokens[4], "ipv4") == 0) {
823 p.common.ip_version = 1;
824 } else if (strcmp(tokens[4], "ipv6") == 0) {
825 p.common.ip_version = 0;
827 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6");
831 if (strcmp(tokens[5], "offset") != 0) {
832 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
836 if (softnic_parser_read_uint32(&p.common.ip_offset,
838 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset");
842 if (strcmp(tokens[7], "fwd") != 0) {
843 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd");
847 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD;
851 (strcmp(tokens[t0], "balance") == 0)) {
852 if (n_tokens < t0 + 7) {
853 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance");
857 if (strcmp(tokens[t0 + 1], "offset") != 0) {
858 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
862 if (softnic_parser_read_uint32(&p.lb.key_offset,
863 tokens[t0 + 2]) != 0) {
864 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
868 if (strcmp(tokens[t0 + 3], "mask") != 0) {
869 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
873 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX;
874 if (softnic_parse_hex_string(tokens[t0 + 4],
875 p.lb.key_mask, &p.lb.key_size) != 0) {
876 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
880 if (strcmp(tokens[t0 + 5], "outoffset") != 0) {
881 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset");
885 if (softnic_parser_read_uint32(&p.lb.out_offset,
886 tokens[t0 + 6]) != 0) {
887 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset");
891 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB;
896 (strcmp(tokens[t0], "meter") == 0)) {
897 if (n_tokens < t0 + 6) {
898 snprintf(out, out_size, MSG_ARG_MISMATCH,
899 "table action profile meter");
903 if (strcmp(tokens[t0 + 1], "srtcm") == 0) {
904 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM;
905 } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) {
906 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM;
908 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
913 if (strcmp(tokens[t0 + 2], "tc") != 0) {
914 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc");
918 if (softnic_parser_read_uint32(&p.mtr.n_tc,
919 tokens[t0 + 3]) != 0) {
920 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc");
924 if (strcmp(tokens[t0 + 4], "stats") != 0) {
925 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
929 if (strcmp(tokens[t0 + 5], "none") == 0) {
930 p.mtr.n_packets_enabled = 0;
931 p.mtr.n_bytes_enabled = 0;
932 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) {
933 p.mtr.n_packets_enabled = 1;
934 p.mtr.n_bytes_enabled = 0;
935 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) {
936 p.mtr.n_packets_enabled = 0;
937 p.mtr.n_bytes_enabled = 1;
938 } else if (strcmp(tokens[t0 + 5], "both") == 0) {
939 p.mtr.n_packets_enabled = 1;
940 p.mtr.n_bytes_enabled = 1;
942 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
943 "none or pkts or bytes or both");
947 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR;
952 (strcmp(tokens[t0], "tm") == 0)) {
953 if (n_tokens < t0 + 5) {
954 snprintf(out, out_size, MSG_ARG_MISMATCH,
955 "table action profile tm");
959 if (strcmp(tokens[t0 + 1], "spp") != 0) {
960 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp");
964 if (softnic_parser_read_uint32(&p.tm.n_subports_per_port,
965 tokens[t0 + 2]) != 0) {
966 snprintf(out, out_size, MSG_ARG_INVALID,
967 "n_subports_per_port");
971 if (strcmp(tokens[t0 + 3], "pps") != 0) {
972 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps");
976 if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport,
977 tokens[t0 + 4]) != 0) {
978 snprintf(out, out_size, MSG_ARG_INVALID,
979 "n_pipes_per_subport");
983 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM;
988 (strcmp(tokens[t0], "encap") == 0)) {
989 if (n_tokens < t0 + 2) {
990 snprintf(out, out_size, MSG_ARG_MISMATCH,
991 "action profile encap");
995 if (strcmp(tokens[t0 + 1], "ether") == 0) {
996 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER;
997 } else if (strcmp(tokens[t0 + 1], "vlan") == 0) {
998 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN;
999 } else if (strcmp(tokens[t0 + 1], "qinq") == 0) {
1000 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ;
1001 } else if (strcmp(tokens[t0 + 1], "mpls") == 0) {
1002 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS;
1003 } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) {
1004 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE;
1006 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap");
1010 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP;
1014 if (t0 < n_tokens &&
1015 (strcmp(tokens[t0], "nat") == 0)) {
1016 if (n_tokens < t0 + 4) {
1017 snprintf(out, out_size, MSG_ARG_MISMATCH,
1018 "table action profile nat");
1022 if (strcmp(tokens[t0 + 1], "src") == 0) {
1023 p.nat.source_nat = 1;
1024 } else if (strcmp(tokens[t0 + 1], "dst") == 0) {
1025 p.nat.source_nat = 0;
1027 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1032 if (strcmp(tokens[t0 + 2], "proto") != 0) {
1033 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto");
1037 if (strcmp(tokens[t0 + 3], "tcp") == 0) {
1039 } else if (strcmp(tokens[t0 + 3], "udp") == 0) {
1042 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1047 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT;
1051 if (t0 < n_tokens &&
1052 (strcmp(tokens[t0], "ttl") == 0)) {
1053 if (n_tokens < t0 + 4) {
1054 snprintf(out, out_size, MSG_ARG_MISMATCH,
1055 "table action profile ttl");
1059 if (strcmp(tokens[t0 + 1], "drop") == 0) {
1061 } else if (strcmp(tokens[t0 + 1], "fwd") == 0) {
1064 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1069 if (strcmp(tokens[t0 + 2], "stats") != 0) {
1070 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1074 if (strcmp(tokens[t0 + 3], "none") == 0) {
1075 p.ttl.n_packets_enabled = 0;
1076 } else if (strcmp(tokens[t0 + 3], "pkts") == 0) {
1077 p.ttl.n_packets_enabled = 1;
1079 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1084 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL;
1088 if (t0 < n_tokens &&
1089 (strcmp(tokens[t0], "stats") == 0)) {
1090 if (n_tokens < t0 + 2) {
1091 snprintf(out, out_size, MSG_ARG_MISMATCH,
1092 "table action profile stats");
1096 if (strcmp(tokens[t0 + 1], "pkts") == 0) {
1097 p.stats.n_packets_enabled = 1;
1098 p.stats.n_bytes_enabled = 0;
1099 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) {
1100 p.stats.n_packets_enabled = 0;
1101 p.stats.n_bytes_enabled = 1;
1102 } else if (strcmp(tokens[t0 + 1], "both") == 0) {
1103 p.stats.n_packets_enabled = 1;
1104 p.stats.n_bytes_enabled = 1;
1106 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1107 "pkts or bytes or both");
1111 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS;
1115 if (t0 < n_tokens &&
1116 (strcmp(tokens[t0], "time") == 0)) {
1117 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME;
1121 if (t0 < n_tokens) {
1122 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1126 ap = softnic_table_action_profile_create(softnic, name, &p);
1128 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1134 * pipeline <pipeline_name>
1135 * period <timer_period_ms>
1136 * offset_port_id <offset_port_id>
1139 cmd_pipeline(struct pmd_internals *softnic,
1145 struct pipeline_params p;
1147 struct pipeline *pipeline;
1149 if (n_tokens != 6) {
1150 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1156 if (strcmp(tokens[2], "period") != 0) {
1157 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period");
1161 if (softnic_parser_read_uint32(&p.timer_period_ms,
1163 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms");
1167 if (strcmp(tokens[4], "offset_port_id") != 0) {
1168 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id");
1172 if (softnic_parser_read_uint32(&p.offset_port_id,
1174 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id");
1178 pipeline = softnic_pipeline_create(softnic, name, &p);
1179 if (pipeline == NULL) {
1180 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1186 * pipeline <pipeline_name> port in
1188 * link <link_name> rxq <queue_id>
1190 * | tmgr <tmgr_name>
1191 * | tap <tap_name> mempool <mempool_name> mtu <mtu>
1192 * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>
1193 * [action <port_in_action_profile_name>]
1197 cmd_pipeline_port_in(struct pmd_internals *softnic,
1203 struct softnic_port_in_params p;
1204 char *pipeline_name;
1206 int enabled, status;
1209 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1213 pipeline_name = tokens[1];
1215 if (strcmp(tokens[2], "port") != 0) {
1216 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1220 if (strcmp(tokens[3], "in") != 0) {
1221 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1225 if (strcmp(tokens[4], "bsz") != 0) {
1226 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1230 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1231 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1237 if (strcmp(tokens[t0], "link") == 0) {
1238 if (n_tokens < t0 + 4) {
1239 snprintf(out, out_size, MSG_ARG_MISMATCH,
1240 "pipeline port in link");
1244 p.type = PORT_IN_RXQ;
1246 p.dev_name = tokens[t0 + 1];
1248 if (strcmp(tokens[t0 + 2], "rxq") != 0) {
1249 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq");
1253 if (softnic_parser_read_uint16(&p.rxq.queue_id,
1254 tokens[t0 + 3]) != 0) {
1255 snprintf(out, out_size, MSG_ARG_INVALID,
1260 } else if (strcmp(tokens[t0], "swq") == 0) {
1261 if (n_tokens < t0 + 2) {
1262 snprintf(out, out_size, MSG_ARG_MISMATCH,
1263 "pipeline port in swq");
1267 p.type = PORT_IN_SWQ;
1269 p.dev_name = tokens[t0 + 1];
1272 } else if (strcmp(tokens[t0], "tmgr") == 0) {
1273 if (n_tokens < t0 + 2) {
1274 snprintf(out, out_size, MSG_ARG_MISMATCH,
1275 "pipeline port in tmgr");
1279 p.type = PORT_IN_TMGR;
1281 p.dev_name = tokens[t0 + 1];
1284 } else if (strcmp(tokens[t0], "tap") == 0) {
1285 if (n_tokens < t0 + 6) {
1286 snprintf(out, out_size, MSG_ARG_MISMATCH,
1287 "pipeline port in tap");
1291 p.type = PORT_IN_TAP;
1293 p.dev_name = tokens[t0 + 1];
1295 if (strcmp(tokens[t0 + 2], "mempool") != 0) {
1296 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1301 p.tap.mempool_name = tokens[t0 + 3];
1303 if (strcmp(tokens[t0 + 4], "mtu") != 0) {
1304 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1309 if (softnic_parser_read_uint32(&p.tap.mtu,
1310 tokens[t0 + 5]) != 0) {
1311 snprintf(out, out_size, MSG_ARG_INVALID, "mtu");
1316 } else if (strcmp(tokens[t0], "source") == 0) {
1317 if (n_tokens < t0 + 6) {
1318 snprintf(out, out_size, MSG_ARG_MISMATCH,
1319 "pipeline port in source");
1323 p.type = PORT_IN_SOURCE;
1327 if (strcmp(tokens[t0 + 1], "mempool") != 0) {
1328 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1333 p.source.mempool_name = tokens[t0 + 2];
1335 if (strcmp(tokens[t0 + 3], "file") != 0) {
1336 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1341 p.source.file_name = tokens[t0 + 4];
1343 if (strcmp(tokens[t0 + 5], "bpp") != 0) {
1344 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1349 if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt,
1350 tokens[t0 + 6]) != 0) {
1351 snprintf(out, out_size, MSG_ARG_INVALID,
1358 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1362 p.action_profile_name = NULL;
1363 if (n_tokens > t0 &&
1364 (strcmp(tokens[t0], "action") == 0)) {
1365 if (n_tokens < t0 + 2) {
1366 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1370 p.action_profile_name = tokens[t0 + 1];
1376 if (n_tokens > t0 &&
1377 (strcmp(tokens[t0], "disabled") == 0)) {
1383 if (n_tokens != t0) {
1384 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1388 status = softnic_pipeline_port_in_create(softnic,
1393 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1399 * pipeline <pipeline_name> port out
1401 * link <link_name> txq <txq_id>
1403 * | tmgr <tmgr_name>
1405 * | sink [file <file_name> pkts <max_n_pkts>]
1408 cmd_pipeline_port_out(struct pmd_internals *softnic,
1414 struct softnic_port_out_params p;
1415 char *pipeline_name;
1418 memset(&p, 0, sizeof(p));
1421 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1425 pipeline_name = tokens[1];
1427 if (strcmp(tokens[2], "port") != 0) {
1428 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1432 if (strcmp(tokens[3], "out") != 0) {
1433 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
1437 if (strcmp(tokens[4], "bsz") != 0) {
1438 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz");
1442 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) {
1443 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size");
1447 if (strcmp(tokens[6], "link") == 0) {
1448 if (n_tokens != 10) {
1449 snprintf(out, out_size, MSG_ARG_MISMATCH,
1450 "pipeline port out link");
1454 p.type = PORT_OUT_TXQ;
1456 p.dev_name = tokens[7];
1458 if (strcmp(tokens[8], "txq") != 0) {
1459 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq");
1463 if (softnic_parser_read_uint16(&p.txq.queue_id,
1465 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id");
1468 } else if (strcmp(tokens[6], "swq") == 0) {
1469 if (n_tokens != 8) {
1470 snprintf(out, out_size, MSG_ARG_MISMATCH,
1471 "pipeline port out swq");
1475 p.type = PORT_OUT_SWQ;
1477 p.dev_name = tokens[7];
1478 } else if (strcmp(tokens[6], "tmgr") == 0) {
1479 if (n_tokens != 8) {
1480 snprintf(out, out_size, MSG_ARG_MISMATCH,
1481 "pipeline port out tmgr");
1485 p.type = PORT_OUT_TMGR;
1487 p.dev_name = tokens[7];
1488 } else if (strcmp(tokens[6], "tap") == 0) {
1489 if (n_tokens != 8) {
1490 snprintf(out, out_size, MSG_ARG_MISMATCH,
1491 "pipeline port out tap");
1495 p.type = PORT_OUT_TAP;
1497 p.dev_name = tokens[7];
1498 } else if (strcmp(tokens[6], "sink") == 0) {
1499 if ((n_tokens != 7) && (n_tokens != 11)) {
1500 snprintf(out, out_size, MSG_ARG_MISMATCH,
1501 "pipeline port out sink");
1505 p.type = PORT_OUT_SINK;
1509 if (n_tokens == 7) {
1510 p.sink.file_name = NULL;
1511 p.sink.max_n_pkts = 0;
1513 if (strcmp(tokens[7], "file") != 0) {
1514 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1519 p.sink.file_name = tokens[8];
1521 if (strcmp(tokens[9], "pkts") != 0) {
1522 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts");
1526 if (softnic_parser_read_uint32(&p.sink.max_n_pkts,
1528 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts");
1533 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1537 status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p);
1539 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1545 * pipeline <pipeline_name> table
1549 * offset <ip_header_offset>
1552 * offset <key_offset>
1558 * offset <key_offset>
1559 * buckets <n_buckets>
1563 * offset <ip_header_offset>
1566 * [action <table_action_profile_name>]
1569 cmd_pipeline_table(struct pmd_internals *softnic,
1575 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX];
1576 struct softnic_table_params p;
1577 char *pipeline_name;
1582 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1586 pipeline_name = tokens[1];
1588 if (strcmp(tokens[2], "table") != 0) {
1589 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1593 if (strcmp(tokens[3], "match") != 0) {
1594 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
1599 if (strcmp(tokens[t0], "acl") == 0) {
1600 if (n_tokens < t0 + 6) {
1601 snprintf(out, out_size, MSG_ARG_MISMATCH,
1602 "pipeline table acl");
1606 p.match_type = TABLE_ACL;
1608 if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
1609 p.match.acl.ip_version = 1;
1610 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
1611 p.match.acl.ip_version = 0;
1613 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1618 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1619 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1623 if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset,
1624 tokens[t0 + 3]) != 0) {
1625 snprintf(out, out_size, MSG_ARG_INVALID,
1626 "ip_header_offset");
1630 if (strcmp(tokens[t0 + 4], "size") != 0) {
1631 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1635 if (softnic_parser_read_uint32(&p.match.acl.n_rules,
1636 tokens[t0 + 5]) != 0) {
1637 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
1642 } else if (strcmp(tokens[t0], "array") == 0) {
1643 if (n_tokens < t0 + 5) {
1644 snprintf(out, out_size, MSG_ARG_MISMATCH,
1645 "pipeline table array");
1649 p.match_type = TABLE_ARRAY;
1651 if (strcmp(tokens[t0 + 1], "offset") != 0) {
1652 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1656 if (softnic_parser_read_uint32(&p.match.array.key_offset,
1657 tokens[t0 + 2]) != 0) {
1658 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1662 if (strcmp(tokens[t0 + 3], "size") != 0) {
1663 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1667 if (softnic_parser_read_uint32(&p.match.array.n_keys,
1668 tokens[t0 + 4]) != 0) {
1669 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1674 } else if (strcmp(tokens[t0], "hash") == 0) {
1675 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX;
1677 if (n_tokens < t0 + 12) {
1678 snprintf(out, out_size, MSG_ARG_MISMATCH,
1679 "pipeline table hash");
1683 p.match_type = TABLE_HASH;
1685 if (strcmp(tokens[t0 + 1], "ext") == 0) {
1686 p.match.hash.extendable_bucket = 1;
1687 } else if (strcmp(tokens[t0 + 1], "lru") == 0) {
1688 p.match.hash.extendable_bucket = 0;
1690 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1695 if (strcmp(tokens[t0 + 2], "key") != 0) {
1696 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key");
1700 if ((softnic_parser_read_uint32(&p.match.hash.key_size,
1701 tokens[t0 + 3]) != 0) ||
1702 p.match.hash.key_size == 0 ||
1703 p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) {
1704 snprintf(out, out_size, MSG_ARG_INVALID, "key_size");
1708 if (strcmp(tokens[t0 + 4], "mask") != 0) {
1709 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask");
1713 if ((softnic_parse_hex_string(tokens[t0 + 5],
1714 key_mask, &key_mask_size) != 0) ||
1715 key_mask_size != p.match.hash.key_size) {
1716 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask");
1719 p.match.hash.key_mask = key_mask;
1721 if (strcmp(tokens[t0 + 6], "offset") != 0) {
1722 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1726 if (softnic_parser_read_uint32(&p.match.hash.key_offset,
1727 tokens[t0 + 7]) != 0) {
1728 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1732 if (strcmp(tokens[t0 + 8], "buckets") != 0) {
1733 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets");
1737 if (softnic_parser_read_uint32(&p.match.hash.n_buckets,
1738 tokens[t0 + 9]) != 0) {
1739 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets");
1743 if (strcmp(tokens[t0 + 10], "size") != 0) {
1744 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1748 if (softnic_parser_read_uint32(&p.match.hash.n_keys,
1749 tokens[t0 + 11]) != 0) {
1750 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys");
1755 } else if (strcmp(tokens[t0], "lpm") == 0) {
1756 if (n_tokens < t0 + 6) {
1757 snprintf(out, out_size, MSG_ARG_MISMATCH,
1758 "pipeline table lpm");
1762 p.match_type = TABLE_LPM;
1764 if (strcmp(tokens[t0 + 1], "ipv4") == 0) {
1765 p.match.lpm.key_size = 4;
1766 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) {
1767 p.match.lpm.key_size = 16;
1769 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
1774 if (strcmp(tokens[t0 + 2], "offset") != 0) {
1775 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset");
1779 if (softnic_parser_read_uint32(&p.match.lpm.key_offset,
1780 tokens[t0 + 3]) != 0) {
1781 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset");
1785 if (strcmp(tokens[t0 + 4], "size") != 0) {
1786 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size");
1790 if (softnic_parser_read_uint32(&p.match.lpm.n_rules,
1791 tokens[t0 + 5]) != 0) {
1792 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
1797 } else if (strcmp(tokens[t0], "stub") == 0) {
1798 p.match_type = TABLE_STUB;
1802 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
1806 p.action_profile_name = NULL;
1807 if (n_tokens > t0 &&
1808 (strcmp(tokens[t0], "action") == 0)) {
1809 if (n_tokens < t0 + 2) {
1810 snprintf(out, out_size, MSG_ARG_MISMATCH, "action");
1814 p.action_profile_name = tokens[t0 + 1];
1819 if (n_tokens > t0) {
1820 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1824 status = softnic_pipeline_table_create(softnic, pipeline_name, &p);
1826 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1832 * pipeline <pipeline_name> port in <port_id> table <table_id>
1835 cmd_pipeline_port_in_table(struct pmd_internals *softnic,
1841 char *pipeline_name;
1842 uint32_t port_id, table_id;
1845 if (n_tokens != 7) {
1846 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1850 pipeline_name = tokens[1];
1852 if (strcmp(tokens[2], "port") != 0) {
1853 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1857 if (strcmp(tokens[3], "in") != 0) {
1858 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1862 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
1863 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
1867 if (strcmp(tokens[5], "table") != 0) {
1868 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
1872 if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) {
1873 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
1877 status = softnic_pipeline_port_in_connect_to_table(softnic,
1882 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1888 * pipeline <pipeline_name> port in <port_id> stats read [clear]
1891 #define MSG_PIPELINE_PORT_IN_STATS \
1892 "Pkts in: %" PRIu64 "\n" \
1893 "Pkts dropped by AH: %" PRIu64 "\n" \
1894 "Pkts dropped by other: %" PRIu64 "\n"
1897 cmd_pipeline_port_in_stats(struct pmd_internals *softnic,
1903 struct rte_pipeline_port_in_stats stats;
1904 char *pipeline_name;
1908 if (n_tokens != 7 &&
1910 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1914 pipeline_name = tokens[1];
1916 if (strcmp(tokens[2], "port") != 0) {
1917 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1921 if (strcmp(tokens[3], "in") != 0) {
1922 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1926 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
1927 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
1931 if (strcmp(tokens[5], "stats") != 0) {
1932 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
1936 if (strcmp(tokens[6], "read") != 0) {
1937 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
1942 if (n_tokens == 8) {
1943 if (strcmp(tokens[7], "clear") != 0) {
1944 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
1951 status = softnic_pipeline_port_in_stats_read(softnic,
1957 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
1961 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS,
1962 stats.stats.n_pkts_in,
1963 stats.n_pkts_dropped_by_ah,
1964 stats.stats.n_pkts_drop);
1968 * pipeline <pipeline_name> port in <port_id> enable
1971 cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic,
1977 char *pipeline_name;
1981 if (n_tokens != 6) {
1982 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
1986 pipeline_name = tokens[1];
1988 if (strcmp(tokens[2], "port") != 0) {
1989 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
1993 if (strcmp(tokens[3], "in") != 0) {
1994 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
1998 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
1999 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2003 if (strcmp(tokens[5], "enable") != 0) {
2004 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
2008 status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id);
2010 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2016 * pipeline <pipeline_name> port in <port_id> disable
2019 cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic,
2025 char *pipeline_name;
2029 if (n_tokens != 6) {
2030 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2034 pipeline_name = tokens[1];
2036 if (strcmp(tokens[2], "port") != 0) {
2037 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2041 if (strcmp(tokens[3], "in") != 0) {
2042 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in");
2046 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
2047 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2051 if (strcmp(tokens[5], "disable") != 0) {
2052 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
2056 status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id);
2058 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2064 * pipeline <pipeline_name> port out <port_id> stats read [clear]
2066 #define MSG_PIPELINE_PORT_OUT_STATS \
2067 "Pkts in: %" PRIu64 "\n" \
2068 "Pkts dropped by AH: %" PRIu64 "\n" \
2069 "Pkts dropped by other: %" PRIu64 "\n"
2072 cmd_pipeline_port_out_stats(struct pmd_internals *softnic,
2078 struct rte_pipeline_port_out_stats stats;
2079 char *pipeline_name;
2083 if (n_tokens != 7 &&
2085 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2089 pipeline_name = tokens[1];
2091 if (strcmp(tokens[2], "port") != 0) {
2092 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2096 if (strcmp(tokens[3], "out") != 0) {
2097 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out");
2101 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) {
2102 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
2106 if (strcmp(tokens[5], "stats") != 0) {
2107 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2111 if (strcmp(tokens[6], "read") != 0) {
2112 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2117 if (n_tokens == 8) {
2118 if (strcmp(tokens[7], "clear") != 0) {
2119 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2126 status = softnic_pipeline_port_out_stats_read(softnic,
2132 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2136 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS,
2137 stats.stats.n_pkts_in,
2138 stats.n_pkts_dropped_by_ah,
2139 stats.stats.n_pkts_drop);
2143 * pipeline <pipeline_name> table <table_id> stats read [clear]
2145 #define MSG_PIPELINE_TABLE_STATS \
2146 "Pkts in: %" PRIu64 "\n" \
2147 "Pkts in with lookup miss: %" PRIu64 "\n" \
2148 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \
2149 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \
2150 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \
2151 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n"
2154 cmd_pipeline_table_stats(struct pmd_internals *softnic,
2160 struct rte_pipeline_table_stats stats;
2161 char *pipeline_name;
2165 if (n_tokens != 6 &&
2167 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2171 pipeline_name = tokens[1];
2173 if (strcmp(tokens[2], "table") != 0) {
2174 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
2178 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
2179 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
2183 if (strcmp(tokens[4], "stats") != 0) {
2184 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats");
2188 if (strcmp(tokens[5], "read") != 0) {
2189 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read");
2194 if (n_tokens == 7) {
2195 if (strcmp(tokens[6], "clear") != 0) {
2196 snprintf(out, out_size, MSG_ARG_INVALID, "clear");
2203 status = softnic_pipeline_table_stats_read(softnic,
2209 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
2213 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS,
2214 stats.stats.n_pkts_in,
2215 stats.stats.n_pkts_lookup_miss,
2216 stats.n_pkts_dropped_by_lkp_hit_ah,
2217 stats.n_pkts_dropped_lkp_hit,
2218 stats.n_pkts_dropped_by_lkp_miss_ah,
2219 stats.n_pkts_dropped_lkp_miss);
2227 * priority <priority>
2228 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth>
2229 * <sp0> <sp1> <dp0> <dp1> <proto>
2233 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto>
2234 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto>
2235 * | ipv4_addr <addr>
2236 * | ipv6_addr <addr>
2237 * | qinq <svlan> <cvlan>
2239 * ipv4 | ipv6 <addr> <depth>
2241 struct pkt_key_qinq {
2242 uint16_t ethertype_svlan;
2244 uint16_t ethertype_cvlan;
2246 } __attribute__((__packed__));
2248 struct pkt_key_ipv4_5tuple {
2249 uint8_t time_to_live;
2251 uint16_t hdr_checksum;
2256 } __attribute__((__packed__));
2258 struct pkt_key_ipv6_5tuple {
2259 uint16_t payload_length;
2266 } __attribute__((__packed__));
2268 struct pkt_key_ipv4_addr {
2270 } __attribute__((__packed__));
2272 struct pkt_key_ipv6_addr {
2274 } __attribute__((__packed__));
2277 parse_match(char **tokens,
2281 struct softnic_table_rule_match *m)
2283 memset(m, 0, sizeof(*m));
2288 if (strcmp(tokens[0], "match") != 0) {
2289 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match");
2293 if (strcmp(tokens[1], "acl") == 0) {
2294 if (n_tokens < 14) {
2295 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2299 m->match_type = TABLE_ACL;
2301 if (strcmp(tokens[2], "priority") != 0) {
2302 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority");
2306 if (softnic_parser_read_uint32(&m->match.acl.priority,
2308 snprintf(out, out_size, MSG_ARG_INVALID, "priority");
2312 if (strcmp(tokens[4], "ipv4") == 0) {
2313 struct in_addr saddr, daddr;
2315 m->match.acl.ip_version = 1;
2317 if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) {
2318 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2321 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr);
2323 if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) {
2324 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2327 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr);
2328 } else if (strcmp(tokens[4], "ipv6") == 0) {
2329 struct in6_addr saddr, daddr;
2331 m->match.acl.ip_version = 0;
2333 if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) {
2334 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2337 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16);
2339 if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) {
2340 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2343 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16);
2345 snprintf(out, out_size, MSG_ARG_NOT_FOUND,
2350 if (softnic_parser_read_uint32(&m->match.acl.sa_depth,
2352 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth");
2356 if (softnic_parser_read_uint32(&m->match.acl.da_depth,
2358 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth");
2362 if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) {
2363 snprintf(out, out_size, MSG_ARG_INVALID, "sp0");
2367 if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) {
2368 snprintf(out, out_size, MSG_ARG_INVALID, "sp1");
2372 if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) {
2373 snprintf(out, out_size, MSG_ARG_INVALID, "dp0");
2377 if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) {
2378 snprintf(out, out_size, MSG_ARG_INVALID, "dp1");
2382 if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) {
2383 snprintf(out, out_size, MSG_ARG_INVALID, "proto");
2387 m->match.acl.proto_mask = 0xff;
2392 if (strcmp(tokens[1], "array") == 0) {
2394 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2398 m->match_type = TABLE_ARRAY;
2400 if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) {
2401 snprintf(out, out_size, MSG_ARG_INVALID, "pos");
2408 if (strcmp(tokens[1], "hash") == 0) {
2410 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2414 m->match_type = TABLE_HASH;
2416 if (strcmp(tokens[2], "raw") == 0) {
2417 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX;
2420 snprintf(out, out_size, MSG_ARG_MISMATCH,
2425 if (softnic_parse_hex_string(tokens[3],
2426 m->match.hash.key, &key_size) != 0) {
2427 snprintf(out, out_size, MSG_ARG_INVALID, "key");
2434 if (strcmp(tokens[2], "ipv4_5tuple") == 0) {
2435 struct pkt_key_ipv4_5tuple *ipv4 =
2436 (struct pkt_key_ipv4_5tuple *)m->match.hash.key;
2437 struct in_addr saddr, daddr;
2442 snprintf(out, out_size, MSG_ARG_MISMATCH,
2447 if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) {
2448 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2452 if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) {
2453 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2457 if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
2458 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2462 if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
2463 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2467 if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
2468 snprintf(out, out_size, MSG_ARG_INVALID,
2473 ipv4->sa = saddr.s_addr;
2474 ipv4->da = daddr.s_addr;
2475 ipv4->sp = rte_cpu_to_be_16(sp);
2476 ipv4->dp = rte_cpu_to_be_16(dp);
2477 ipv4->proto = proto;
2480 } /* hash ipv4_5tuple */
2482 if (strcmp(tokens[2], "ipv6_5tuple") == 0) {
2483 struct pkt_key_ipv6_5tuple *ipv6 =
2484 (struct pkt_key_ipv6_5tuple *)m->match.hash.key;
2485 struct in6_addr saddr, daddr;
2490 snprintf(out, out_size, MSG_ARG_MISMATCH,
2495 if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) {
2496 snprintf(out, out_size, MSG_ARG_INVALID, "sa");
2500 if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) {
2501 snprintf(out, out_size, MSG_ARG_INVALID, "da");
2505 if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) {
2506 snprintf(out, out_size, MSG_ARG_INVALID, "sp");
2510 if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) {
2511 snprintf(out, out_size, MSG_ARG_INVALID, "dp");
2515 if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) {
2516 snprintf(out, out_size, MSG_ARG_INVALID,
2521 memcpy(ipv6->sa, saddr.s6_addr, 16);
2522 memcpy(ipv6->da, daddr.s6_addr, 16);
2523 ipv6->sp = rte_cpu_to_be_16(sp);
2524 ipv6->dp = rte_cpu_to_be_16(dp);
2525 ipv6->proto = proto;
2528 } /* hash ipv6_5tuple */
2530 if (strcmp(tokens[2], "ipv4_addr") == 0) {
2531 struct pkt_key_ipv4_addr *ipv4_addr =
2532 (struct pkt_key_ipv4_addr *)m->match.hash.key;
2533 struct in_addr addr;
2536 snprintf(out, out_size, MSG_ARG_MISMATCH,
2541 if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
2542 snprintf(out, out_size, MSG_ARG_INVALID,
2547 ipv4_addr->addr = addr.s_addr;
2550 } /* hash ipv4_addr */
2552 if (strcmp(tokens[2], "ipv6_addr") == 0) {
2553 struct pkt_key_ipv6_addr *ipv6_addr =
2554 (struct pkt_key_ipv6_addr *)m->match.hash.key;
2555 struct in6_addr addr;
2558 snprintf(out, out_size, MSG_ARG_MISMATCH,
2563 if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
2564 snprintf(out, out_size, MSG_ARG_INVALID,
2569 memcpy(ipv6_addr->addr, addr.s6_addr, 16);
2572 } /* hash ipv6_5tuple */
2574 if (strcmp(tokens[2], "qinq") == 0) {
2575 struct pkt_key_qinq *qinq =
2576 (struct pkt_key_qinq *)m->match.hash.key;
2577 uint16_t svlan, cvlan;
2580 snprintf(out, out_size, MSG_ARG_MISMATCH,
2585 if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) ||
2587 snprintf(out, out_size, MSG_ARG_INVALID,
2592 if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) ||
2594 snprintf(out, out_size, MSG_ARG_INVALID,
2599 qinq->svlan = rte_cpu_to_be_16(svlan);
2600 qinq->cvlan = rte_cpu_to_be_16(cvlan);
2605 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2609 if (strcmp(tokens[1], "lpm") == 0) {
2611 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
2615 m->match_type = TABLE_LPM;
2617 if (strcmp(tokens[2], "ipv4") == 0) {
2618 struct in_addr addr;
2620 m->match.lpm.ip_version = 1;
2622 if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) {
2623 snprintf(out, out_size, MSG_ARG_INVALID,
2628 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr);
2629 } else if (strcmp(tokens[2], "ipv6") == 0) {
2630 struct in6_addr addr;
2632 m->match.lpm.ip_version = 0;
2634 if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) {
2635 snprintf(out, out_size, MSG_ARG_INVALID,
2640 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16);
2642 snprintf(out, out_size, MSG_ARG_MISMATCH,
2647 if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) {
2648 snprintf(out, out_size, MSG_ARG_INVALID, "depth");
2655 snprintf(out, out_size, MSG_ARG_MISMATCH,
2656 "acl or array or hash or lpm");
2668 * | table <table_id>
2669 * [balance <out0> ... <out7>]
2671 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2672 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2673 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa>
2674 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]]
2675 * [tm subport <subport_id> pipe <pipe_id>]
2678 * | vlan <da> <sa> <pcp> <dei> <vid>
2679 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid>
2680 * | mpls unicast | multicast
2682 * label0 <label> <tc> <ttl>
2683 * [label1 <label> <tc> <ttl>
2684 * [label2 <label> <tc> <ttl>
2685 * [label3 <label> <tc> <ttl>]]]
2686 * | pppoe <da> <sa> <session_id>]
2687 * [nat ipv4 | ipv6 <addr> <port>]
2693 * <pa> ::= g | y | r | drop
2696 parse_table_action_fwd(char **tokens,
2698 struct softnic_table_rule_action *a)
2700 if (n_tokens == 0 ||
2701 (strcmp(tokens[0], "fwd") != 0))
2707 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) {
2708 a->fwd.action = RTE_PIPELINE_ACTION_DROP;
2709 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2713 if (n_tokens && (strcmp(tokens[0], "port") == 0)) {
2717 softnic_parser_read_uint32(&id, tokens[1]))
2720 a->fwd.action = RTE_PIPELINE_ACTION_PORT;
2722 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2726 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) {
2727 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META;
2728 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2732 if (n_tokens && (strcmp(tokens[0], "table") == 0)) {
2736 softnic_parser_read_uint32(&id, tokens[1]))
2739 a->fwd.action = RTE_PIPELINE_ACTION_TABLE;
2741 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD;
2749 parse_table_action_balance(char **tokens,
2751 struct softnic_table_rule_action *a)
2755 if (n_tokens == 0 ||
2756 (strcmp(tokens[0], "balance") != 0))
2762 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE)
2765 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++)
2766 if (softnic_parser_read_uint32(&a->lb.out[i], tokens[i]) != 0)
2769 a->action_mask |= 1 << RTE_TABLE_ACTION_LB;
2770 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE;
2774 parse_policer_action(char *token, enum rte_table_action_policer *a)
2776 if (strcmp(token, "g") == 0) {
2777 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN;
2781 if (strcmp(token, "y") == 0) {
2782 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW;
2786 if (strcmp(token, "r") == 0) {
2787 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED;
2791 if (strcmp(token, "drop") == 0) {
2792 *a = RTE_TABLE_ACTION_POLICER_DROP;
2800 parse_table_action_meter_tc(char **tokens,
2802 struct rte_table_action_mtr_tc_params *mtr)
2805 strcmp(tokens[0], "meter") ||
2806 softnic_parser_read_uint32(&mtr->meter_profile_id, tokens[1]) ||
2807 strcmp(tokens[2], "policer") ||
2808 strcmp(tokens[3], "g") ||
2809 parse_policer_action(tokens[4], &mtr->policer[e_RTE_METER_GREEN]) ||
2810 strcmp(tokens[5], "y") ||
2811 parse_policer_action(tokens[6], &mtr->policer[e_RTE_METER_YELLOW]) ||
2812 strcmp(tokens[7], "r") ||
2813 parse_policer_action(tokens[8], &mtr->policer[e_RTE_METER_RED]))
2820 parse_table_action_meter(char **tokens,
2822 struct softnic_table_rule_action *a)
2824 if (n_tokens == 0 ||
2825 strcmp(tokens[0], "meter"))
2831 if (n_tokens < 10 ||
2832 strcmp(tokens[0], "tc0") ||
2833 (parse_table_action_meter_tc(tokens + 1,
2835 &a->mtr.mtr[0]) == 0))
2841 if (n_tokens == 0 ||
2842 strcmp(tokens[0], "tc1")) {
2844 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
2848 if (n_tokens < 30 ||
2849 (parse_table_action_meter_tc(tokens + 1,
2850 n_tokens - 1, &a->mtr.mtr[1]) == 0) ||
2851 strcmp(tokens[10], "tc2") ||
2852 (parse_table_action_meter_tc(tokens + 11,
2853 n_tokens - 11, &a->mtr.mtr[2]) == 0) ||
2854 strcmp(tokens[20], "tc3") ||
2855 (parse_table_action_meter_tc(tokens + 21,
2856 n_tokens - 21, &a->mtr.mtr[3]) == 0))
2859 a->mtr.tc_mask = 0xF;
2860 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR;
2861 return 1 + 10 + 3 * 10;
2865 parse_table_action_tm(char **tokens,
2867 struct softnic_table_rule_action *a)
2869 uint32_t subport_id, pipe_id;
2872 strcmp(tokens[0], "tm") ||
2873 strcmp(tokens[1], "subport") ||
2874 softnic_parser_read_uint32(&subport_id, tokens[2]) ||
2875 strcmp(tokens[3], "pipe") ||
2876 softnic_parser_read_uint32(&pipe_id, tokens[4]))
2879 a->tm.subport_id = subport_id;
2880 a->tm.pipe_id = pipe_id;
2881 a->action_mask |= 1 << RTE_TABLE_ACTION_TM;
2886 parse_table_action_encap(char **tokens,
2888 struct softnic_table_rule_action *a)
2890 if (n_tokens == 0 ||
2891 strcmp(tokens[0], "encap"))
2898 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) {
2900 softnic_parse_mac_addr(tokens[1], &a->encap.ether.ether.da) ||
2901 softnic_parse_mac_addr(tokens[2], &a->encap.ether.ether.sa))
2904 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER;
2905 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
2910 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) {
2911 uint32_t pcp, dei, vid;
2914 softnic_parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) ||
2915 softnic_parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) ||
2916 softnic_parser_read_uint32(&pcp, tokens[3]) ||
2918 softnic_parser_read_uint32(&dei, tokens[4]) ||
2920 softnic_parser_read_uint32(&vid, tokens[5]) ||
2924 a->encap.vlan.vlan.pcp = pcp & 0x7;
2925 a->encap.vlan.vlan.dei = dei & 0x1;
2926 a->encap.vlan.vlan.vid = vid & 0xFFF;
2927 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN;
2928 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
2933 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) {
2934 uint32_t svlan_pcp, svlan_dei, svlan_vid;
2935 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid;
2938 softnic_parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) ||
2939 softnic_parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) ||
2940 softnic_parser_read_uint32(&svlan_pcp, tokens[3]) ||
2942 softnic_parser_read_uint32(&svlan_dei, tokens[4]) ||
2944 softnic_parser_read_uint32(&svlan_vid, tokens[5]) ||
2945 svlan_vid > 0xFFF ||
2946 softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) ||
2948 softnic_parser_read_uint32(&cvlan_dei, tokens[7]) ||
2950 softnic_parser_read_uint32(&cvlan_vid, tokens[8]) ||
2954 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7;
2955 a->encap.qinq.svlan.dei = svlan_dei & 0x1;
2956 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF;
2957 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7;
2958 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1;
2959 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF;
2960 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ;
2961 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
2966 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) {
2967 uint32_t label, tc, ttl;
2972 if (strcmp(tokens[1], "unicast") == 0)
2973 a->encap.mpls.unicast = 1;
2974 else if (strcmp(tokens[1], "multicast") == 0)
2975 a->encap.mpls.unicast = 0;
2979 if (softnic_parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) ||
2980 softnic_parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) ||
2981 strcmp(tokens[4], "label0") ||
2982 softnic_parser_read_uint32(&label, tokens[5]) ||
2984 softnic_parser_read_uint32(&tc, tokens[6]) ||
2986 softnic_parser_read_uint32(&ttl, tokens[7]) ||
2990 a->encap.mpls.mpls[0].label = label;
2991 a->encap.mpls.mpls[0].tc = tc;
2992 a->encap.mpls.mpls[0].ttl = ttl;
2997 if (n_tokens == 0 ||
2998 strcmp(tokens[0], "label1")) {
2999 a->encap.mpls.mpls_count = 1;
3000 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3001 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3006 softnic_parser_read_uint32(&label, tokens[1]) ||
3008 softnic_parser_read_uint32(&tc, tokens[2]) ||
3010 softnic_parser_read_uint32(&ttl, tokens[3]) ||
3014 a->encap.mpls.mpls[1].label = label;
3015 a->encap.mpls.mpls[1].tc = tc;
3016 a->encap.mpls.mpls[1].ttl = ttl;
3021 if (n_tokens == 0 ||
3022 strcmp(tokens[0], "label2")) {
3023 a->encap.mpls.mpls_count = 2;
3024 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3025 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3030 softnic_parser_read_uint32(&label, tokens[1]) ||
3032 softnic_parser_read_uint32(&tc, tokens[2]) ||
3034 softnic_parser_read_uint32(&ttl, tokens[3]) ||
3038 a->encap.mpls.mpls[2].label = label;
3039 a->encap.mpls.mpls[2].tc = tc;
3040 a->encap.mpls.mpls[2].ttl = ttl;
3045 if (n_tokens == 0 ||
3046 strcmp(tokens[0], "label3")) {
3047 a->encap.mpls.mpls_count = 3;
3048 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3049 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3050 return 1 + 8 + 4 + 4;
3054 softnic_parser_read_uint32(&label, tokens[1]) ||
3056 softnic_parser_read_uint32(&tc, tokens[2]) ||
3058 softnic_parser_read_uint32(&ttl, tokens[3]) ||
3062 a->encap.mpls.mpls[3].label = label;
3063 a->encap.mpls.mpls[3].tc = tc;
3064 a->encap.mpls.mpls[3].ttl = ttl;
3066 a->encap.mpls.mpls_count = 4;
3067 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS;
3068 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3069 return 1 + 8 + 4 + 4 + 4;
3073 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) {
3075 softnic_parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) ||
3076 softnic_parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) ||
3077 softnic_parser_read_uint16(&a->encap.pppoe.pppoe.session_id,
3081 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE;
3082 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP;
3090 parse_table_action_nat(char **tokens,
3092 struct softnic_table_rule_action *a)
3095 strcmp(tokens[0], "nat"))
3098 if (strcmp(tokens[1], "ipv4") == 0) {
3099 struct in_addr addr;
3102 if (softnic_parse_ipv4_addr(tokens[2], &addr) ||
3103 softnic_parser_read_uint16(&port, tokens[3]))
3106 a->nat.ip_version = 1;
3107 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr);
3109 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3113 if (strcmp(tokens[1], "ipv6") == 0) {
3114 struct in6_addr addr;
3117 if (softnic_parse_ipv6_addr(tokens[2], &addr) ||
3118 softnic_parser_read_uint16(&port, tokens[3]))
3121 a->nat.ip_version = 0;
3122 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16);
3124 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT;
3132 parse_table_action_ttl(char **tokens,
3134 struct softnic_table_rule_action *a)
3137 strcmp(tokens[0], "ttl"))
3140 if (strcmp(tokens[1], "dec") == 0)
3141 a->ttl.decrement = 1;
3142 else if (strcmp(tokens[1], "keep") == 0)
3143 a->ttl.decrement = 0;
3147 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL;
3152 parse_table_action_stats(char **tokens,
3154 struct softnic_table_rule_action *a)
3157 strcmp(tokens[0], "stats"))
3160 a->stats.n_packets = 0;
3161 a->stats.n_bytes = 0;
3162 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS;
3167 parse_table_action_time(char **tokens,
3169 struct softnic_table_rule_action *a)
3172 strcmp(tokens[0], "time"))
3175 a->time.time = rte_rdtsc();
3176 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME;
3181 parse_table_action(char **tokens,
3185 struct softnic_table_rule_action *a)
3187 uint32_t n_tokens0 = n_tokens;
3189 memset(a, 0, sizeof(*a));
3192 strcmp(tokens[0], "action"))
3198 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) {
3201 n = parse_table_action_fwd(tokens, n_tokens, a);
3203 snprintf(out, out_size, MSG_ARG_INVALID,
3212 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) {
3215 n = parse_table_action_balance(tokens, n_tokens, a);
3217 snprintf(out, out_size, MSG_ARG_INVALID,
3226 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) {
3229 n = parse_table_action_meter(tokens, n_tokens, a);
3231 snprintf(out, out_size, MSG_ARG_INVALID,
3240 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) {
3243 n = parse_table_action_tm(tokens, n_tokens, a);
3245 snprintf(out, out_size, MSG_ARG_INVALID,
3254 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) {
3257 n = parse_table_action_encap(tokens, n_tokens, a);
3259 snprintf(out, out_size, MSG_ARG_INVALID,
3268 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) {
3271 n = parse_table_action_nat(tokens, n_tokens, a);
3273 snprintf(out, out_size, MSG_ARG_INVALID,
3282 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) {
3285 n = parse_table_action_ttl(tokens, n_tokens, a);
3287 snprintf(out, out_size, MSG_ARG_INVALID,
3296 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) {
3299 n = parse_table_action_stats(tokens, n_tokens, a);
3301 snprintf(out, out_size, MSG_ARG_INVALID,
3310 if (n_tokens && (strcmp(tokens[0], "time") == 0)) {
3313 n = parse_table_action_time(tokens, n_tokens, a);
3315 snprintf(out, out_size, MSG_ARG_INVALID,
3324 if (n_tokens0 - n_tokens == 1) {
3325 snprintf(out, out_size, MSG_ARG_INVALID, "action");
3329 return n_tokens0 - n_tokens;
3333 * pipeline <pipeline_name> table <table_id> rule add
3335 * action <table_action>
3338 cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic,
3344 struct softnic_table_rule_match m;
3345 struct softnic_table_rule_action a;
3346 char *pipeline_name;
3348 uint32_t table_id, t0, n_tokens_parsed;
3352 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3356 pipeline_name = tokens[1];
3358 if (strcmp(tokens[2], "table") != 0) {
3359 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3363 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3364 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3368 if (strcmp(tokens[4], "rule") != 0) {
3369 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3373 if (strcmp(tokens[5], "add") != 0) {
3374 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3381 n_tokens_parsed = parse_match(tokens + t0,
3386 if (n_tokens_parsed == 0)
3388 t0 += n_tokens_parsed;
3391 n_tokens_parsed = parse_table_action(tokens + t0,
3396 if (n_tokens_parsed == 0)
3398 t0 += n_tokens_parsed;
3400 if (t0 != n_tokens) {
3401 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]);
3405 status = softnic_pipeline_table_rule_add(softnic,
3412 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3418 * pipeline <pipeline_name> table <table_id> rule add
3426 * | table <table_id>
3429 cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic,
3435 struct softnic_table_rule_action action;
3437 char *pipeline_name;
3441 if (n_tokens != 11 &&
3443 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3447 pipeline_name = tokens[1];
3449 if (strcmp(tokens[2], "table") != 0) {
3450 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3454 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3455 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3459 if (strcmp(tokens[4], "rule") != 0) {
3460 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3464 if (strcmp(tokens[5], "add") != 0) {
3465 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3469 if (strcmp(tokens[6], "match") != 0) {
3470 snprintf(out, out_size, MSG_ARG_INVALID, "match");
3474 if (strcmp(tokens[7], "default") != 0) {
3475 snprintf(out, out_size, MSG_ARG_INVALID, "default");
3479 if (strcmp(tokens[8], "action") != 0) {
3480 snprintf(out, out_size, MSG_ARG_INVALID, "action");
3484 if (strcmp(tokens[9], "fwd") != 0) {
3485 snprintf(out, out_size, MSG_ARG_INVALID, "fwd");
3489 action.action_mask = 1 << RTE_TABLE_ACTION_FWD;
3491 if (strcmp(tokens[10], "drop") == 0) {
3492 if (n_tokens != 11) {
3493 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3497 action.fwd.action = RTE_PIPELINE_ACTION_DROP;
3498 } else if (strcmp(tokens[10], "port") == 0) {
3501 if (n_tokens != 12) {
3502 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3506 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
3507 snprintf(out, out_size, MSG_ARG_INVALID, "port_id");
3511 action.fwd.action = RTE_PIPELINE_ACTION_PORT;
3513 } else if (strcmp(tokens[10], "meta") == 0) {
3514 if (n_tokens != 11) {
3515 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3519 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META;
3520 } else if (strcmp(tokens[10], "table") == 0) {
3523 if (n_tokens != 12) {
3524 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3528 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) {
3529 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3533 action.fwd.action = RTE_PIPELINE_ACTION_TABLE;
3536 snprintf(out, out_size, MSG_ARG_INVALID,
3537 "drop or port or meta or table");
3541 status = softnic_pipeline_table_rule_add_default(softnic,
3547 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3553 * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>
3556 * - line format: match <match> action <action>
3559 cli_rule_file_process(const char *file_name,
3560 size_t line_len_max,
3561 struct softnic_table_rule_match *m,
3562 struct softnic_table_rule_action *a,
3564 uint32_t *line_number,
3569 cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic,
3575 struct softnic_table_rule_match *match;
3576 struct softnic_table_rule_action *action;
3578 char *pipeline_name, *file_name;
3579 uint32_t table_id, n_rules, n_rules_parsed, line_number;
3582 if (n_tokens != 9) {
3583 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3587 pipeline_name = tokens[1];
3589 if (strcmp(tokens[2], "table") != 0) {
3590 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3594 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3595 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3599 if (strcmp(tokens[4], "rule") != 0) {
3600 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3604 if (strcmp(tokens[5], "add") != 0) {
3605 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3609 if (strcmp(tokens[6], "bulk") != 0) {
3610 snprintf(out, out_size, MSG_ARG_INVALID, "bulk");
3614 file_name = tokens[7];
3616 if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) ||
3618 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules");
3622 /* Memory allocation. */
3623 match = calloc(n_rules, sizeof(struct softnic_table_rule_match));
3624 action = calloc(n_rules, sizeof(struct softnic_table_rule_action));
3625 data = calloc(n_rules, sizeof(void *));
3626 if (match == NULL ||
3629 snprintf(out, out_size, MSG_OUT_OF_MEMORY);
3636 /* Load rule file */
3637 n_rules_parsed = n_rules;
3638 status = cli_rule_file_process(file_name,
3647 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
3653 if (n_rules_parsed != n_rules) {
3654 snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name);
3662 status = softnic_pipeline_table_rule_add_bulk(softnic,
3670 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3684 * pipeline <pipeline_name> table <table_id> rule delete
3688 cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic,
3694 struct softnic_table_rule_match m;
3695 char *pipeline_name;
3696 uint32_t table_id, n_tokens_parsed, t0;
3700 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3704 pipeline_name = tokens[1];
3706 if (strcmp(tokens[2], "table") != 0) {
3707 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3711 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3712 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3716 if (strcmp(tokens[4], "rule") != 0) {
3717 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3721 if (strcmp(tokens[5], "delete") != 0) {
3722 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
3729 n_tokens_parsed = parse_match(tokens + t0,
3734 if (n_tokens_parsed == 0)
3736 t0 += n_tokens_parsed;
3738 if (n_tokens != t0) {
3739 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3743 status = softnic_pipeline_table_rule_delete(softnic,
3748 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3754 * pipeline <pipeline_name> table <table_id> rule delete
3759 cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic,
3765 char *pipeline_name;
3769 if (n_tokens != 8) {
3770 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3774 pipeline_name = tokens[1];
3776 if (strcmp(tokens[2], "table") != 0) {
3777 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table");
3781 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3782 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3786 if (strcmp(tokens[4], "rule") != 0) {
3787 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule");
3791 if (strcmp(tokens[5], "delete") != 0) {
3792 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
3796 if (strcmp(tokens[6], "match") != 0) {
3797 snprintf(out, out_size, MSG_ARG_INVALID, "match");
3801 if (strcmp(tokens[7], "default") != 0) {
3802 snprintf(out, out_size, MSG_ARG_INVALID, "default");
3806 status = softnic_pipeline_table_rule_delete_default(softnic,
3810 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3816 * pipeline <pipeline_name> table <table_id> rule read stats [clear]
3819 cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused,
3821 uint32_t n_tokens __rte_unused,
3825 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
3829 * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>
3830 * add srtcm cir <cir> cbs <cbs> ebs <ebs>
3831 * | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>
3834 cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic,
3840 struct rte_table_action_meter_profile p;
3841 char *pipeline_name;
3842 uint32_t table_id, meter_profile_id;
3846 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3850 pipeline_name = tokens[1];
3852 if (strcmp(tokens[2], "table") != 0) {
3853 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
3857 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
3858 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
3862 if (strcmp(tokens[4], "meter") != 0) {
3863 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
3867 if (strcmp(tokens[5], "profile") != 0) {
3868 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
3872 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
3873 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
3877 if (strcmp(tokens[7], "add") != 0) {
3878 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add");
3882 if (strcmp(tokens[8], "srtcm") == 0) {
3883 if (n_tokens != 15) {
3884 snprintf(out, out_size, MSG_ARG_MISMATCH,
3889 p.alg = RTE_TABLE_ACTION_METER_SRTCM;
3891 if (strcmp(tokens[9], "cir") != 0) {
3892 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
3896 if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) {
3897 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
3901 if (strcmp(tokens[11], "cbs") != 0) {
3902 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
3906 if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) {
3907 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
3911 if (strcmp(tokens[13], "ebs") != 0) {
3912 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs");
3916 if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) {
3917 snprintf(out, out_size, MSG_ARG_INVALID, "ebs");
3920 } else if (strcmp(tokens[8], "trtcm") == 0) {
3921 if (n_tokens != 17) {
3922 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3926 p.alg = RTE_TABLE_ACTION_METER_TRTCM;
3928 if (strcmp(tokens[9], "cir") != 0) {
3929 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir");
3933 if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) {
3934 snprintf(out, out_size, MSG_ARG_INVALID, "cir");
3938 if (strcmp(tokens[11], "pir") != 0) {
3939 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir");
3943 if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) {
3944 snprintf(out, out_size, MSG_ARG_INVALID, "pir");
3947 if (strcmp(tokens[13], "cbs") != 0) {
3948 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs");
3952 if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) {
3953 snprintf(out, out_size, MSG_ARG_INVALID, "cbs");
3957 if (strcmp(tokens[15], "pbs") != 0) {
3958 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs");
3962 if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) {
3963 snprintf(out, out_size, MSG_ARG_INVALID, "pbs");
3967 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
3971 status = softnic_pipeline_table_mtr_profile_add(softnic,
3977 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
3983 * pipeline <pipeline_name> table <table_id>
3984 * meter profile <meter_profile_id> delete
3987 cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic,
3993 char *pipeline_name;
3994 uint32_t table_id, meter_profile_id;
3997 if (n_tokens != 8) {
3998 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4002 pipeline_name = tokens[1];
4004 if (strcmp(tokens[2], "table") != 0) {
4005 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
4009 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
4010 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4014 if (strcmp(tokens[4], "meter") != 0) {
4015 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter");
4019 if (strcmp(tokens[5], "profile") != 0) {
4020 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile");
4024 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) {
4025 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id");
4029 if (strcmp(tokens[7], "delete") != 0) {
4030 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete");
4034 status = softnic_pipeline_table_mtr_profile_delete(softnic,
4039 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4045 * pipeline <pipeline_name> table <table_id> rule read meter [clear]
4048 cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused,
4050 uint32_t n_tokens __rte_unused,
4054 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
4058 * pipeline <pipeline_name> table <table_id> dscp <file_name>
4061 * - exactly 64 lines
4062 * - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r
4065 load_dscp_table(struct rte_table_action_dscp_table *dscp_table,
4066 const char *file_name,
4067 uint32_t *line_number)
4072 /* Check input arguments */
4073 if (dscp_table == NULL ||
4074 file_name == NULL ||
4075 line_number == NULL) {
4081 /* Open input file */
4082 f = fopen(file_name, "r");
4089 for (dscp = 0, l = 1; ; l++) {
4092 enum rte_meter_color color;
4093 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens);
4095 if (fgets(line, sizeof(line), f) == NULL)
4098 if (is_comment(line))
4101 if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) {
4110 if (dscp >= RTE_DIM(dscp_table->entry) ||
4111 n_tokens != RTE_DIM(tokens) ||
4112 softnic_parser_read_uint32(&tc_id, tokens[0]) ||
4113 tc_id >= RTE_TABLE_ACTION_TC_MAX ||
4114 softnic_parser_read_uint32(&tc_queue_id, tokens[1]) ||
4115 tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX ||
4116 (strlen(tokens[2]) != 1)) {
4122 switch (tokens[2][0]) {
4125 color = e_RTE_METER_GREEN;
4130 color = e_RTE_METER_YELLOW;
4135 color = e_RTE_METER_RED;
4144 dscp_table->entry[dscp].tc_id = tc_id;
4145 dscp_table->entry[dscp].tc_queue_id = tc_queue_id;
4146 dscp_table->entry[dscp].color = color;
4156 cmd_pipeline_table_dscp(struct pmd_internals *softnic,
4162 struct rte_table_action_dscp_table dscp_table;
4163 char *pipeline_name, *file_name;
4164 uint32_t table_id, line_number;
4167 if (n_tokens != 6) {
4168 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4172 pipeline_name = tokens[1];
4174 if (strcmp(tokens[2], "table") != 0) {
4175 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port");
4179 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) {
4180 snprintf(out, out_size, MSG_ARG_INVALID, "table_id");
4184 if (strcmp(tokens[4], "dscp") != 0) {
4185 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp");
4189 file_name = tokens[5];
4191 status = load_dscp_table(&dscp_table, file_name, &line_number);
4193 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number);
4197 status = softnic_pipeline_table_dscp_table_update(softnic,
4203 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]);
4209 * pipeline <pipeline_name> table <table_id> rule read ttl [clear]
4212 cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused,
4214 uint32_t n_tokens __rte_unused,
4218 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]);
4222 * thread <thread_id> pipeline <pipeline_name> enable
4225 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic,
4231 char *pipeline_name;
4235 if (n_tokens != 5) {
4236 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4240 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
4241 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
4245 if (strcmp(tokens[2], "pipeline") != 0) {
4246 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
4250 pipeline_name = tokens[3];
4252 if (strcmp(tokens[4], "enable") != 0) {
4253 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable");
4257 status = softnic_thread_pipeline_enable(softnic, thread_id, pipeline_name);
4259 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable");
4265 * thread <thread_id> pipeline <pipeline_name> disable
4268 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic,
4274 char *pipeline_name;
4278 if (n_tokens != 5) {
4279 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]);
4283 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) {
4284 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id");
4288 if (strcmp(tokens[2], "pipeline") != 0) {
4289 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline");
4293 pipeline_name = tokens[3];
4295 if (strcmp(tokens[4], "disable") != 0) {
4296 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable");
4300 status = softnic_thread_pipeline_disable(softnic, thread_id, pipeline_name);
4302 snprintf(out, out_size, MSG_CMD_FAIL,
4303 "thread pipeline disable");
4309 softnic_cli_process(char *in, char *out, size_t out_size, void *arg)
4311 char *tokens[CMD_MAX_TOKENS];
4312 uint32_t n_tokens = RTE_DIM(tokens);
4313 struct pmd_internals *softnic = arg;
4319 status = softnic_parse_tokenize_string(in, tokens, &n_tokens);
4321 snprintf(out, out_size, MSG_ARG_TOO_MANY, "");
4328 if (strcmp(tokens[0], "mempool") == 0) {
4329 cmd_mempool(softnic, tokens, n_tokens, out, out_size);
4333 if (strcmp(tokens[0], "link") == 0) {
4334 cmd_link(softnic, tokens, n_tokens, out, out_size);
4338 if (strcmp(tokens[0], "swq") == 0) {
4339 cmd_swq(softnic, tokens, n_tokens, out, out_size);
4343 if (strcmp(tokens[0], "tmgr") == 0) {
4344 if (n_tokens == 2) {
4345 cmd_tmgr(softnic, tokens, n_tokens, out, out_size);
4349 if (n_tokens >= 3 &&
4350 (strcmp(tokens[1], "shaper") == 0) &&
4351 (strcmp(tokens[2], "profile") == 0)) {
4352 cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size);
4356 if (n_tokens >= 3 &&
4357 (strcmp(tokens[1], "shared") == 0) &&
4358 (strcmp(tokens[2], "shaper") == 0)) {
4359 cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size);
4363 if (n_tokens >= 2 &&
4364 (strcmp(tokens[1], "node") == 0)) {
4365 cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size);
4369 if (n_tokens >= 3 &&
4370 (strcmp(tokens[1], "hierarchy") == 0) &&
4371 (strcmp(tokens[2], "commit") == 0)) {
4372 cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size);
4377 if (strcmp(tokens[0], "tap") == 0) {
4378 cmd_tap(softnic, tokens, n_tokens, out, out_size);
4382 if (strcmp(tokens[0], "port") == 0) {
4383 cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size);
4387 if (strcmp(tokens[0], "table") == 0) {
4388 cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size);
4392 if (strcmp(tokens[0], "pipeline") == 0) {
4393 if (n_tokens >= 3 &&
4394 (strcmp(tokens[2], "period") == 0)) {
4395 cmd_pipeline(softnic, tokens, n_tokens, out, out_size);
4399 if (n_tokens >= 5 &&
4400 (strcmp(tokens[2], "port") == 0) &&
4401 (strcmp(tokens[3], "in") == 0) &&
4402 (strcmp(tokens[4], "bsz") == 0)) {
4403 cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size);
4407 if (n_tokens >= 5 &&
4408 (strcmp(tokens[2], "port") == 0) &&
4409 (strcmp(tokens[3], "out") == 0) &&
4410 (strcmp(tokens[4], "bsz") == 0)) {
4411 cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size);
4415 if (n_tokens >= 4 &&
4416 (strcmp(tokens[2], "table") == 0) &&
4417 (strcmp(tokens[3], "match") == 0)) {
4418 cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size);
4422 if (n_tokens >= 6 &&
4423 (strcmp(tokens[2], "port") == 0) &&
4424 (strcmp(tokens[3], "in") == 0) &&
4425 (strcmp(tokens[5], "table") == 0)) {
4426 cmd_pipeline_port_in_table(softnic, tokens, n_tokens,
4431 if (n_tokens >= 6 &&
4432 (strcmp(tokens[2], "port") == 0) &&
4433 (strcmp(tokens[3], "in") == 0) &&
4434 (strcmp(tokens[5], "stats") == 0)) {
4435 cmd_pipeline_port_in_stats(softnic, tokens, n_tokens,
4440 if (n_tokens >= 6 &&
4441 (strcmp(tokens[2], "port") == 0) &&
4442 (strcmp(tokens[3], "in") == 0) &&
4443 (strcmp(tokens[5], "enable") == 0)) {
4444 cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens,
4449 if (n_tokens >= 6 &&
4450 (strcmp(tokens[2], "port") == 0) &&
4451 (strcmp(tokens[3], "in") == 0) &&
4452 (strcmp(tokens[5], "disable") == 0)) {
4453 cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens,
4458 if (n_tokens >= 6 &&
4459 (strcmp(tokens[2], "port") == 0) &&
4460 (strcmp(tokens[3], "out") == 0) &&
4461 (strcmp(tokens[5], "stats") == 0)) {
4462 cmd_pipeline_port_out_stats(softnic, tokens, n_tokens,
4467 if (n_tokens >= 5 &&
4468 (strcmp(tokens[2], "table") == 0) &&
4469 (strcmp(tokens[4], "stats") == 0)) {
4470 cmd_pipeline_table_stats(softnic, tokens, n_tokens,
4475 if (n_tokens >= 7 &&
4476 (strcmp(tokens[2], "table") == 0) &&
4477 (strcmp(tokens[4], "rule") == 0) &&
4478 (strcmp(tokens[5], "add") == 0) &&
4479 (strcmp(tokens[6], "match") == 0)) {
4480 if (n_tokens >= 8 &&
4481 (strcmp(tokens[7], "default") == 0)) {
4482 cmd_softnic_pipeline_table_rule_add_default(softnic, tokens,
4483 n_tokens, out, out_size);
4487 cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens,
4492 if (n_tokens >= 7 &&
4493 (strcmp(tokens[2], "table") == 0) &&
4494 (strcmp(tokens[4], "rule") == 0) &&
4495 (strcmp(tokens[5], "add") == 0) &&
4496 (strcmp(tokens[6], "bulk") == 0)) {
4497 cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens,
4498 n_tokens, out, out_size);
4502 if (n_tokens >= 7 &&
4503 (strcmp(tokens[2], "table") == 0) &&
4504 (strcmp(tokens[4], "rule") == 0) &&
4505 (strcmp(tokens[5], "delete") == 0) &&
4506 (strcmp(tokens[6], "match") == 0)) {
4507 if (n_tokens >= 8 &&
4508 (strcmp(tokens[7], "default") == 0)) {
4509 cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens,
4510 n_tokens, out, out_size);
4514 cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens,
4519 if (n_tokens >= 7 &&
4520 (strcmp(tokens[2], "table") == 0) &&
4521 (strcmp(tokens[4], "rule") == 0) &&
4522 (strcmp(tokens[5], "read") == 0) &&
4523 (strcmp(tokens[6], "stats") == 0)) {
4524 cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens,
4529 if (n_tokens >= 8 &&
4530 (strcmp(tokens[2], "table") == 0) &&
4531 (strcmp(tokens[4], "meter") == 0) &&
4532 (strcmp(tokens[5], "profile") == 0) &&
4533 (strcmp(tokens[7], "add") == 0)) {
4534 cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens,
4539 if (n_tokens >= 8 &&
4540 (strcmp(tokens[2], "table") == 0) &&
4541 (strcmp(tokens[4], "meter") == 0) &&
4542 (strcmp(tokens[5], "profile") == 0) &&
4543 (strcmp(tokens[7], "delete") == 0)) {
4544 cmd_pipeline_table_meter_profile_delete(softnic, tokens,
4545 n_tokens, out, out_size);
4549 if (n_tokens >= 7 &&
4550 (strcmp(tokens[2], "table") == 0) &&
4551 (strcmp(tokens[4], "rule") == 0) &&
4552 (strcmp(tokens[5], "read") == 0) &&
4553 (strcmp(tokens[6], "meter") == 0)) {
4554 cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens,
4559 if (n_tokens >= 5 &&
4560 (strcmp(tokens[2], "table") == 0) &&
4561 (strcmp(tokens[4], "dscp") == 0)) {
4562 cmd_pipeline_table_dscp(softnic, tokens, n_tokens,
4567 if (n_tokens >= 7 &&
4568 (strcmp(tokens[2], "table") == 0) &&
4569 (strcmp(tokens[4], "rule") == 0) &&
4570 (strcmp(tokens[5], "read") == 0) &&
4571 (strcmp(tokens[6], "ttl") == 0)) {
4572 cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens,
4578 if (strcmp(tokens[0], "thread") == 0) {
4579 if (n_tokens >= 5 &&
4580 (strcmp(tokens[4], "enable") == 0)) {
4581 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens,
4586 if (n_tokens >= 5 &&
4587 (strcmp(tokens[4], "disable") == 0)) {
4588 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens,
4594 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]);
4598 softnic_cli_script_process(struct pmd_internals *softnic,
4599 const char *file_name,
4600 size_t msg_in_len_max,
4601 size_t msg_out_len_max)
4603 char *msg_in = NULL, *msg_out = NULL;
4606 /* Check input arguments */
4607 if (file_name == NULL ||
4608 (strlen(file_name) == 0) ||
4609 msg_in_len_max == 0 ||
4610 msg_out_len_max == 0)
4613 msg_in = malloc(msg_in_len_max + 1);
4614 msg_out = malloc(msg_out_len_max + 1);
4615 if (msg_in == NULL ||
4622 /* Open input file */
4623 f = fopen(file_name, "r");
4632 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL)
4635 printf("%s", msg_in);
4638 softnic_cli_process(msg_in,
4643 if (strlen(msg_out))
4644 printf("%s", msg_out);
4655 cli_rule_file_process(const char *file_name,
4656 size_t line_len_max,
4657 struct softnic_table_rule_match *m,
4658 struct softnic_table_rule_action *a,
4660 uint32_t *line_number,
4666 uint32_t rule_id, line_id;
4669 /* Check input arguments */
4670 if (file_name == NULL ||
4671 (strlen(file_name) == 0) ||
4672 line_len_max == 0) {
4677 /* Memory allocation */
4678 line = malloc(line_len_max + 1);
4685 f = fopen(file_name, "r");
4693 for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) {
4694 char *tokens[CMD_MAX_TOKENS];
4695 uint32_t n_tokens, n_tokens_parsed, t0;
4697 /* Read next line from file. */
4698 if (fgets(line, line_len_max + 1, f) == NULL)
4702 if (is_comment(line))
4706 n_tokens = RTE_DIM(tokens);
4707 status = softnic_parse_tokenize_string(line, tokens, &n_tokens);
4719 n_tokens_parsed = parse_match(tokens + t0,
4724 if (n_tokens_parsed == 0) {
4728 t0 += n_tokens_parsed;
4731 n_tokens_parsed = parse_table_action(tokens + t0,
4736 if (n_tokens_parsed == 0) {
4740 t0 += n_tokens_parsed;
4742 /* Line completed. */
4743 if (t0 < n_tokens) {
4748 /* Increment rule count */
4759 *line_number = line_id;