From b63264c8342e6a1b6971c79550d2af2024b6a4de Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Tue, 14 Aug 2018 18:52:30 +0100 Subject: New upstream version 18.08 Change-Id: I32fdf5e5016556d9c0a6d88ddaf1fc468961790a Signed-off-by: Luca Boccassi --- examples/ip_pipeline/Makefile | 55 +- examples/ip_pipeline/action.c | 358 ++ examples/ip_pipeline/action.h | 77 + examples/ip_pipeline/app.h | 1401 ------ examples/ip_pipeline/cli.c | 5240 ++++++++++++++++++++ examples/ip_pipeline/cli.h | 18 + examples/ip_pipeline/common.h | 12 + examples/ip_pipeline/config/action.cfg | 68 - examples/ip_pipeline/config/action.sh | 119 - examples/ip_pipeline/config/action.txt | 8 - examples/ip_pipeline/config/diagram-generator.py | 317 -- .../ip_pipeline/config/edge_router_downstream.cfg | 97 - .../ip_pipeline/config/edge_router_downstream.sh | 13 - .../ip_pipeline/config/edge_router_upstream.cfg | 124 - .../ip_pipeline/config/edge_router_upstream.sh | 33 - examples/ip_pipeline/config/firewall.cfg | 68 - examples/ip_pipeline/config/firewall.sh | 13 - examples/ip_pipeline/config/firewall.txt | 9 - examples/ip_pipeline/config/flow.cfg | 72 - examples/ip_pipeline/config/flow.sh | 25 - examples/ip_pipeline/config/flow.txt | 17 - examples/ip_pipeline/config/ip_pipeline.cfg | 9 - examples/ip_pipeline/config/ip_pipeline.sh | 5 - examples/ip_pipeline/config/kni.cfg | 67 - examples/ip_pipeline/config/l2fwd.cfg | 58 - examples/ip_pipeline/config/l3fwd.cfg | 68 - examples/ip_pipeline/config/l3fwd.sh | 33 - examples/ip_pipeline/config/l3fwd_arp.cfg | 70 - examples/ip_pipeline/config/l3fwd_arp.sh | 43 - examples/ip_pipeline/config/network_layers.cfg | 227 - examples/ip_pipeline/config/network_layers.sh | 79 - .../ip_pipeline/config/pipeline-to-core-mapping.py | 906 ---- examples/ip_pipeline/config/tap.cfg | 64 - examples/ip_pipeline/config/tm_profile.cfg | 105 - examples/ip_pipeline/config_check.c | 488 -- examples/ip_pipeline/config_parse.c | 3395 ------------- examples/ip_pipeline/config_parse_tm.c | 419 -- examples/ip_pipeline/conn.c | 329 ++ examples/ip_pipeline/conn.h | 47 + examples/ip_pipeline/cpu_core_map.c | 471 -- examples/ip_pipeline/cpu_core_map.h | 40 - examples/ip_pipeline/examples/firewall.cli | 59 + examples/ip_pipeline/examples/flow.cli | 60 + examples/ip_pipeline/examples/kni.cli | 69 + examples/ip_pipeline/examples/l2fwd.cli | 51 + examples/ip_pipeline/examples/route.cli | 60 + examples/ip_pipeline/examples/route_ecmp.cli | 57 + examples/ip_pipeline/examples/rss.cli | 112 + examples/ip_pipeline/examples/tap.cli | 66 + examples/ip_pipeline/hash_func.h | 357 ++ examples/ip_pipeline/hash_func_arm64.h | 232 + examples/ip_pipeline/init.c | 1927 ------- examples/ip_pipeline/kni.c | 175 + examples/ip_pipeline/kni.h | 46 + examples/ip_pipeline/link.c | 267 + examples/ip_pipeline/link.h | 66 + examples/ip_pipeline/main.c | 259 +- examples/ip_pipeline/mempool.c | 82 + examples/ip_pipeline/mempool.h | 40 + examples/ip_pipeline/meson.build | 36 +- examples/ip_pipeline/parser.c | 17 +- examples/ip_pipeline/parser.h | 8 + examples/ip_pipeline/pipeline.c | 988 ++++ examples/ip_pipeline/pipeline.h | 389 +- examples/ip_pipeline/pipeline/hash_func.h | 356 -- examples/ip_pipeline/pipeline/hash_func_arm64.h | 261 - .../ip_pipeline/pipeline/pipeline_actions_common.h | 202 - examples/ip_pipeline/pipeline/pipeline_common_be.c | 176 - examples/ip_pipeline/pipeline/pipeline_common_be.h | 134 - examples/ip_pipeline/pipeline/pipeline_common_fe.c | 1455 ------ examples/ip_pipeline/pipeline/pipeline_common_fe.h | 231 - examples/ip_pipeline/pipeline/pipeline_firewall.c | 1421 ------ examples/ip_pipeline/pipeline/pipeline_firewall.h | 60 - .../ip_pipeline/pipeline/pipeline_firewall_be.c | 856 ---- .../ip_pipeline/pipeline/pipeline_firewall_be.h | 147 - .../ip_pipeline/pipeline/pipeline_flow_actions.c | 1286 ----- .../ip_pipeline/pipeline/pipeline_flow_actions.h | 60 - .../pipeline/pipeline_flow_actions_be.c | 960 ---- .../pipeline/pipeline_flow_actions_be.h | 139 - .../pipeline/pipeline_flow_classification.c | 1878 ------- .../pipeline/pipeline_flow_classification.h | 106 - .../pipeline/pipeline_flow_classification_be.c | 723 --- .../pipeline/pipeline_flow_classification_be.h | 113 - examples/ip_pipeline/pipeline/pipeline_master.c | 20 - examples/ip_pipeline/pipeline/pipeline_master.h | 12 - examples/ip_pipeline/pipeline/pipeline_master_be.c | 141 - examples/ip_pipeline/pipeline/pipeline_master_be.h | 12 - .../ip_pipeline/pipeline/pipeline_passthrough.c | 45 - .../ip_pipeline/pipeline/pipeline_passthrough.h | 12 - .../ip_pipeline/pipeline/pipeline_passthrough_be.c | 929 ---- .../ip_pipeline/pipeline/pipeline_passthrough_be.h | 44 - examples/ip_pipeline/pipeline/pipeline_routing.c | 1613 ------ examples/ip_pipeline/pipeline/pipeline_routing.h | 71 - .../ip_pipeline/pipeline/pipeline_routing_be.c | 1966 -------- .../ip_pipeline/pipeline/pipeline_routing_be.h | 283 -- examples/ip_pipeline/pipeline_be.h | 322 -- examples/ip_pipeline/swq.c | 76 + examples/ip_pipeline/swq.h | 37 + examples/ip_pipeline/tap.c | 102 + examples/ip_pipeline/tap.h | 29 + examples/ip_pipeline/thread.c | 3075 +++++++++++- examples/ip_pipeline/thread.h | 75 +- examples/ip_pipeline/thread_fe.c | 457 -- examples/ip_pipeline/thread_fe.h | 72 - examples/ip_pipeline/tmgr.c | 229 + examples/ip_pipeline/tmgr.h | 70 + 106 files changed, 12940 insertions(+), 27806 deletions(-) create mode 100644 examples/ip_pipeline/action.c create mode 100644 examples/ip_pipeline/action.h delete mode 100644 examples/ip_pipeline/app.h create mode 100644 examples/ip_pipeline/cli.c create mode 100644 examples/ip_pipeline/cli.h create mode 100644 examples/ip_pipeline/common.h delete mode 100644 examples/ip_pipeline/config/action.cfg delete mode 100644 examples/ip_pipeline/config/action.sh delete mode 100644 examples/ip_pipeline/config/action.txt delete mode 100755 examples/ip_pipeline/config/diagram-generator.py delete mode 100644 examples/ip_pipeline/config/edge_router_downstream.cfg delete mode 100644 examples/ip_pipeline/config/edge_router_downstream.sh delete mode 100644 examples/ip_pipeline/config/edge_router_upstream.cfg delete mode 100644 examples/ip_pipeline/config/edge_router_upstream.sh delete mode 100644 examples/ip_pipeline/config/firewall.cfg delete mode 100644 examples/ip_pipeline/config/firewall.sh delete mode 100644 examples/ip_pipeline/config/firewall.txt delete mode 100644 examples/ip_pipeline/config/flow.cfg delete mode 100644 examples/ip_pipeline/config/flow.sh delete mode 100644 examples/ip_pipeline/config/flow.txt delete mode 100644 examples/ip_pipeline/config/ip_pipeline.cfg delete mode 100644 examples/ip_pipeline/config/ip_pipeline.sh delete mode 100644 examples/ip_pipeline/config/kni.cfg delete mode 100644 examples/ip_pipeline/config/l2fwd.cfg delete mode 100644 examples/ip_pipeline/config/l3fwd.cfg delete mode 100644 examples/ip_pipeline/config/l3fwd.sh delete mode 100644 examples/ip_pipeline/config/l3fwd_arp.cfg delete mode 100644 examples/ip_pipeline/config/l3fwd_arp.sh delete mode 100644 examples/ip_pipeline/config/network_layers.cfg delete mode 100644 examples/ip_pipeline/config/network_layers.sh delete mode 100755 examples/ip_pipeline/config/pipeline-to-core-mapping.py delete mode 100644 examples/ip_pipeline/config/tap.cfg delete mode 100644 examples/ip_pipeline/config/tm_profile.cfg delete mode 100644 examples/ip_pipeline/config_check.c delete mode 100644 examples/ip_pipeline/config_parse.c delete mode 100644 examples/ip_pipeline/config_parse_tm.c create mode 100644 examples/ip_pipeline/conn.c create mode 100644 examples/ip_pipeline/conn.h delete mode 100644 examples/ip_pipeline/cpu_core_map.c delete mode 100644 examples/ip_pipeline/cpu_core_map.h create mode 100644 examples/ip_pipeline/examples/firewall.cli create mode 100644 examples/ip_pipeline/examples/flow.cli create mode 100644 examples/ip_pipeline/examples/kni.cli create mode 100644 examples/ip_pipeline/examples/l2fwd.cli create mode 100644 examples/ip_pipeline/examples/route.cli create mode 100644 examples/ip_pipeline/examples/route_ecmp.cli create mode 100644 examples/ip_pipeline/examples/rss.cli create mode 100644 examples/ip_pipeline/examples/tap.cli create mode 100644 examples/ip_pipeline/hash_func.h create mode 100644 examples/ip_pipeline/hash_func_arm64.h delete mode 100644 examples/ip_pipeline/init.c create mode 100644 examples/ip_pipeline/kni.c create mode 100644 examples/ip_pipeline/kni.h create mode 100644 examples/ip_pipeline/link.c create mode 100644 examples/ip_pipeline/link.h create mode 100644 examples/ip_pipeline/mempool.c create mode 100644 examples/ip_pipeline/mempool.h create mode 100644 examples/ip_pipeline/pipeline.c delete mode 100644 examples/ip_pipeline/pipeline/hash_func.h delete mode 100644 examples/ip_pipeline/pipeline/hash_func_arm64.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_actions_common.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_common_fe.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_firewall_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_actions_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_flow_classification_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_master_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_passthrough_be.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing.h delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.c delete mode 100644 examples/ip_pipeline/pipeline/pipeline_routing_be.h delete mode 100644 examples/ip_pipeline/pipeline_be.h create mode 100644 examples/ip_pipeline/swq.c create mode 100644 examples/ip_pipeline/swq.h create mode 100644 examples/ip_pipeline/tap.c create mode 100644 examples/ip_pipeline/tap.h delete mode 100644 examples/ip_pipeline/thread_fe.c delete mode 100644 examples/ip_pipeline/thread_fe.h create mode 100644 examples/ip_pipeline/tmgr.c create mode 100644 examples/ip_pipeline/tmgr.h (limited to 'examples/ip_pipeline') diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index 27f7cc6a..3fb98ce3 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -1,34 +1,23 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation +# Copyright(c) 2010-2018 Intel Corporation # binary name APP = ip_pipeline # all source are stored in SRCS-y -SRCS-y := main.c -SRCS-y += config_parse.c +SRCS-y := action.c +SRCS-y += cli.c +SRCS-y += conn.c +SRCS-y += kni.c +SRCS-y += link.c +SRCS-y += main.c +SRCS-y += mempool.c SRCS-y += parser.c -SRCS-y += config_parse_tm.c -SRCS-y += config_check.c -SRCS-y += init.c +SRCS-y += pipeline.c +SRCS-y += swq.c +SRCS-y += tap.c SRCS-y += thread.c -SRCS-y += thread_fe.c -SRCS-y += cpu_core_map.c - -SRCS-y += pipeline_common_be.c -SRCS-y += pipeline_common_fe.c -SRCS-y += pipeline_master_be.c -SRCS-y += pipeline_master.c -SRCS-y += pipeline_passthrough_be.c -SRCS-y += pipeline_passthrough.c -SRCS-y += pipeline_firewall_be.c -SRCS-y += pipeline_firewall.c -SRCS-y += pipeline_flow_classification_be.c -SRCS-y += pipeline_flow_classification.c -SRCS-y += pipeline_flow_actions_be.c -SRCS-y += pipeline_flow_actions.c -SRCS-y += pipeline_routing_be.c -SRCS-y += pipeline_routing.c +SRCS-y += tmgr.c # Build using pkg-config variables if possible $(shell pkg-config --exists libdpdk) @@ -46,8 +35,7 @@ CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) -VPATH += pipeline -CFLAGS += -I. -I./pipeline/ +CFLAGS += -I. OBJS := $(patsubst %.c,build/%.o,$(SRCS-y)) @@ -74,21 +62,28 @@ ifeq ($(RTE_SDK),) $(error "Please define RTE_SDK environment variable") endif -VPATH += $(SRCDIR)/pipeline - # Default target, can be overridden by command line or environment RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -INC += $(sort $(wildcard *.h)) $(sort $(wildcard pipeline/*.h)) +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) +$(info This application can only operate in a linuxapp environment, \ +please change the definition of the RTE_TARGET environment variable) +all: +clean: +else + +INC += $(sort $(wildcard *.h)) SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := $(SRCS-y) -CFLAGS += -I$(SRCDIR) -I$(SRCDIR)/pipeline +CFLAGS += -DALLOW_EXPERIMENTAL_API +CFLAGS += -I$(SRCDIR) CFLAGS += -O3 -CFLAGS += $(WERROR_FLAGS) -Wno-error=unused-function -Wno-error=unused-variable +CFLAGS += $(WERROR_FLAGS) include $(RTE_SDK)/mk/rte.extapp.mk endif +endif diff --git a/examples/ip_pipeline/action.c b/examples/ip_pipeline/action.c new file mode 100644 index 00000000..a29c2b36 --- /dev/null +++ b/examples/ip_pipeline/action.c @@ -0,0 +1,358 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include + +#include + +#include "action.h" +#include "hash_func.h" + +/** + * Input port + */ +static struct port_in_action_profile_list port_in_action_profile_list; + +int +port_in_action_profile_init(void) +{ + TAILQ_INIT(&port_in_action_profile_list); + + return 0; +} + +struct port_in_action_profile * +port_in_action_profile_find(const char *name) +{ + struct port_in_action_profile *profile; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(profile, &port_in_action_profile_list, node) + if (strcmp(profile->name, name) == 0) + return profile; + + return NULL; +} + +struct port_in_action_profile * +port_in_action_profile_create(const char *name, + struct port_in_action_profile_params *params) +{ + struct port_in_action_profile *profile; + struct rte_port_in_action_profile *ap; + int status; + + /* Check input params */ + if ((name == NULL) || + port_in_action_profile_find(name) || + (params == NULL)) + return NULL; + + if ((params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) && + (params->lb.f_hash == NULL)) { + switch (params->lb.key_size) { + case 8: + params->lb.f_hash = hash_default_key8; + break; + + case 16: + params->lb.f_hash = hash_default_key16; + break; + + case 24: + params->lb.f_hash = hash_default_key24; + break; + + case 32: + params->lb.f_hash = hash_default_key32; + break; + + case 40: + params->lb.f_hash = hash_default_key40; + break; + + case 48: + params->lb.f_hash = hash_default_key48; + break; + + case 56: + params->lb.f_hash = hash_default_key56; + break; + + case 64: + params->lb.f_hash = hash_default_key64; + break; + + default: + return NULL; + } + + params->lb.seed = 0; + } + /* Resource */ + ap = rte_port_in_action_profile_create(0); + if (ap == NULL) + return NULL; + + if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_FLTR)) { + status = rte_port_in_action_profile_action_register(ap, + RTE_PORT_IN_ACTION_FLTR, + ¶ms->fltr); + + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_PORT_IN_ACTION_LB)) { + status = rte_port_in_action_profile_action_register(ap, + RTE_PORT_IN_ACTION_LB, + ¶ms->lb); + + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + } + + status = rte_port_in_action_profile_freeze(ap); + if (status) { + rte_port_in_action_profile_free(ap); + return NULL; + } + + /* Node allocation */ + profile = calloc(1, sizeof(struct port_in_action_profile)); + if (profile == NULL) { + rte_port_in_action_profile_free(ap); + return NULL; + } + + /* Node fill in */ + strlcpy(profile->name, name, sizeof(profile->name)); + memcpy(&profile->params, params, sizeof(*params)); + profile->ap = ap; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&port_in_action_profile_list, profile, node); + + return profile; +} + +/** + * Table + */ +static struct table_action_profile_list table_action_profile_list; + +int +table_action_profile_init(void) +{ + TAILQ_INIT(&table_action_profile_list); + + return 0; +} + +struct table_action_profile * +table_action_profile_find(const char *name) +{ + struct table_action_profile *profile; + + if (name == NULL) + return NULL; + + TAILQ_FOREACH(profile, &table_action_profile_list, node) + if (strcmp(profile->name, name) == 0) + return profile; + + return NULL; +} + +struct table_action_profile * +table_action_profile_create(const char *name, + struct table_action_profile_params *params) +{ + struct table_action_profile *profile; + struct rte_table_action_profile *ap; + int status; + + /* Check input params */ + if ((name == NULL) || + table_action_profile_find(name) || + (params == NULL) || + ((params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) == 0)) + return NULL; + + if ((params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) && + (params->lb.f_hash == NULL)) { + switch (params->lb.key_size) { + case 8: + params->lb.f_hash = hash_default_key8; + break; + + case 16: + params->lb.f_hash = hash_default_key16; + break; + + case 24: + params->lb.f_hash = hash_default_key24; + break; + + case 32: + params->lb.f_hash = hash_default_key32; + break; + + case 40: + params->lb.f_hash = hash_default_key40; + break; + + case 48: + params->lb.f_hash = hash_default_key48; + break; + + case 56: + params->lb.f_hash = hash_default_key56; + break; + + case 64: + params->lb.f_hash = hash_default_key64; + break; + + default: + return NULL; + } + + params->lb.seed = 0; + } + + /* Resource */ + ap = rte_table_action_profile_create(¶ms->common); + if (ap == NULL) + return NULL; + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_FWD, + NULL); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_LB, + ¶ms->lb); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_MTR, + ¶ms->mtr); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TM, + ¶ms->tm); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_ENCAP, + ¶ms->encap); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_NAT, + ¶ms->nat); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TTL, + ¶ms->ttl); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_STATS, + ¶ms->stats); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + if (params->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { + status = rte_table_action_profile_action_register(ap, + RTE_TABLE_ACTION_TIME, + NULL); + + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + } + + status = rte_table_action_profile_freeze(ap); + if (status) { + rte_table_action_profile_free(ap); + return NULL; + } + + /* Node allocation */ + profile = calloc(1, sizeof(struct table_action_profile)); + if (profile == NULL) { + rte_table_action_profile_free(ap); + return NULL; + } + + /* Node fill in */ + strlcpy(profile->name, name, sizeof(profile->name)); + memcpy(&profile->params, params, sizeof(*params)); + profile->ap = ap; + + /* Node add to list */ + TAILQ_INSERT_TAIL(&table_action_profile_list, profile, node); + + return profile; +} diff --git a/examples/ip_pipeline/action.h b/examples/ip_pipeline/action.h new file mode 100644 index 00000000..417200e8 --- /dev/null +++ b/examples/ip_pipeline/action.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _INCLUDE_ACTION_H_ +#define _INCLUDE_ACTION_H_ + +#include + +#include +#include + +#include "common.h" + +/** + * Input port action + */ +struct port_in_action_profile_params { + uint64_t action_mask; + struct rte_port_in_action_fltr_config fltr; + struct rte_port_in_action_lb_config lb; +}; + +struct port_in_action_profile { + TAILQ_ENTRY(port_in_action_profile) node; + char name[NAME_SIZE]; + struct port_in_action_profile_params params; + struct rte_port_in_action_profile *ap; +}; + +TAILQ_HEAD(port_in_action_profile_list, port_in_action_profile); + +int +port_in_action_profile_init(void); + +struct port_in_action_profile * +port_in_action_profile_find(const char *name); + +struct port_in_action_profile * +port_in_action_profile_create(const char *name, + struct port_in_action_profile_params *params); + +/** + * Table action + */ +struct table_action_profile_params { + uint64_t action_mask; + struct rte_table_action_common_config common; + struct rte_table_action_lb_config lb; + struct rte_table_action_mtr_config mtr; + struct rte_table_action_tm_config tm; + struct rte_table_action_encap_config encap; + struct rte_table_action_nat_config nat; + struct rte_table_action_ttl_config ttl; + struct rte_table_action_stats_config stats; +}; + +struct table_action_profile { + TAILQ_ENTRY(table_action_profile) node; + char name[NAME_SIZE]; + struct table_action_profile_params params; + struct rte_table_action_profile *ap; +}; + +TAILQ_HEAD(table_action_profile_list, table_action_profile); + +int +table_action_profile_init(void); + +struct table_action_profile * +table_action_profile_find(const char *name); + +struct table_action_profile * +table_action_profile_create(const char *name, + struct table_action_profile_params *params); + +#endif /* _INCLUDE_ACTION_H_ */ diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h deleted file mode 100644 index 907d4e7c..00000000 --- a/examples/ip_pipeline/app.h +++ /dev/null @@ -1,1401 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ - -#ifndef __INCLUDE_APP_H__ -#define __INCLUDE_APP_H__ - -#include -#include - -#include -#include -#include -#include -#include - -#include -#ifdef RTE_LIBRTE_KNI -#include -#endif - -#include "cpu_core_map.h" -#include "pipeline.h" - -#define APP_PARAM_NAME_SIZE PIPELINE_NAME_SIZE -#define APP_LINK_PCI_BDF_SIZE 16 - -#ifndef APP_LINK_MAX_HWQ_IN -#define APP_LINK_MAX_HWQ_IN 128 -#endif - -#ifndef APP_LINK_MAX_HWQ_OUT -#define APP_LINK_MAX_HWQ_OUT 128 -#endif - -struct app_mempool_params { - char *name; - uint32_t parsed; - uint32_t buffer_size; - uint32_t pool_size; - uint32_t cache_size; - uint32_t cpu_socket_id; -}; - -struct app_link_params { - char *name; - uint32_t parsed; - uint32_t pmd_id; /* Generated based on port mask */ - uint32_t arp_q; /* 0 = Disabled (packets go to default queue 0) */ - uint32_t tcp_syn_q; /* 0 = Disabled (pkts go to default queue) */ - uint32_t ip_local_q; /* 0 = Disabled (pkts go to default queue 0) */ - uint32_t tcp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ - uint32_t udp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ - uint32_t sctp_local_q; /* 0 = Disabled (pkts go to default queue 0) */ - uint32_t rss_qs[APP_LINK_MAX_HWQ_IN]; - uint32_t n_rss_qs; - uint64_t rss_proto_ipv4; - uint64_t rss_proto_ipv6; - uint64_t rss_proto_l2; - uint32_t promisc; - uint32_t state; /* DOWN = 0, UP = 1 */ - uint32_t ip; /* 0 = Invalid */ - uint32_t depth; /* Valid only when IP is valid */ - uint64_t mac_addr; /* Read from HW */ - char pci_bdf[APP_LINK_PCI_BDF_SIZE]; - - struct rte_eth_conf conf; -}; - -struct app_pktq_hwq_in_params { - char *name; - uint32_t parsed; - uint32_t mempool_id; /* Position in the app->mempool_params */ - uint32_t size; - uint32_t burst; - - struct rte_eth_rxconf conf; -}; - -struct app_pktq_hwq_out_params { - char *name; - uint32_t parsed; - uint32_t size; - uint32_t burst; - uint32_t dropless; - uint64_t n_retries; - struct rte_eth_txconf conf; -}; - -struct app_pktq_swq_params { - char *name; - uint32_t parsed; - uint32_t size; - uint32_t burst_read; - uint32_t burst_write; - uint32_t dropless; - uint64_t n_retries; - uint32_t cpu_socket_id; - uint32_t ipv4_frag; - uint32_t ipv6_frag; - uint32_t ipv4_ras; - uint32_t ipv6_ras; - uint32_t mtu; - uint32_t metadata_size; - uint32_t mempool_direct_id; - uint32_t mempool_indirect_id; -}; - -struct app_pktq_kni_params { - char *name; - uint32_t parsed; - - uint32_t socket_id; - uint32_t core_id; - uint32_t hyper_th_id; - uint32_t force_bind; - - uint32_t mempool_id; /* Position in the app->mempool_params */ - uint32_t burst_read; - uint32_t burst_write; - uint32_t dropless; - uint64_t n_retries; -}; - -#ifndef APP_FILE_NAME_SIZE -#define APP_FILE_NAME_SIZE 256 -#endif - -#ifndef APP_MAX_SCHED_SUBPORTS -#define APP_MAX_SCHED_SUBPORTS 8 -#endif - -#ifndef APP_MAX_SCHED_PIPES -#define APP_MAX_SCHED_PIPES 4096 -#endif - -struct app_pktq_tm_params { - char *name; - uint32_t parsed; - const char *file_name; - struct rte_sched_port_params sched_port_params; - struct rte_sched_subport_params - sched_subport_params[APP_MAX_SCHED_SUBPORTS]; - struct rte_sched_pipe_params - sched_pipe_profiles[RTE_SCHED_PIPE_PROFILES_PER_PORT]; - int sched_pipe_to_profile[APP_MAX_SCHED_SUBPORTS * APP_MAX_SCHED_PIPES]; - uint32_t burst_read; - uint32_t burst_write; -}; - -struct app_pktq_tap_params { - char *name; - uint32_t parsed; - uint32_t burst_read; - uint32_t burst_write; - uint32_t dropless; - uint64_t n_retries; - uint32_t mempool_id; /* Position in the app->mempool_params */ -}; - -struct app_pktq_source_params { - char *name; - uint32_t parsed; - uint32_t mempool_id; /* Position in the app->mempool_params array */ - uint32_t burst; - const char *file_name; /* Full path of PCAP file to be copied to mbufs */ - uint32_t n_bytes_per_pkt; -}; - -struct app_pktq_sink_params { - char *name; - uint8_t parsed; - const char *file_name; /* Full path of PCAP file to be copied to mbufs */ - uint32_t n_pkts_to_dump; -}; - -struct app_msgq_params { - char *name; - uint32_t parsed; - uint32_t size; - uint32_t cpu_socket_id; -}; - -enum app_pktq_in_type { - APP_PKTQ_IN_HWQ, - APP_PKTQ_IN_SWQ, - APP_PKTQ_IN_TM, - APP_PKTQ_IN_TAP, - APP_PKTQ_IN_KNI, - APP_PKTQ_IN_SOURCE, -}; - -struct app_pktq_in_params { - enum app_pktq_in_type type; - uint32_t id; /* Position in the appropriate app array */ -}; - -enum app_pktq_out_type { - APP_PKTQ_OUT_HWQ, - APP_PKTQ_OUT_SWQ, - APP_PKTQ_OUT_TM, - APP_PKTQ_OUT_TAP, - APP_PKTQ_OUT_KNI, - APP_PKTQ_OUT_SINK, -}; - -struct app_pktq_out_params { - enum app_pktq_out_type type; - uint32_t id; /* Position in the appropriate app array */ -}; - -#define APP_PIPELINE_TYPE_SIZE PIPELINE_TYPE_SIZE - -#define APP_MAX_PIPELINE_PKTQ_IN PIPELINE_MAX_PORT_IN -#define APP_MAX_PIPELINE_PKTQ_OUT PIPELINE_MAX_PORT_OUT -#define APP_MAX_PIPELINE_MSGQ_IN PIPELINE_MAX_MSGQ_IN -#define APP_MAX_PIPELINE_MSGQ_OUT PIPELINE_MAX_MSGQ_OUT - -#define APP_MAX_PIPELINE_ARGS PIPELINE_MAX_ARGS - -struct app_pipeline_params { - char *name; - uint8_t parsed; - - char type[APP_PIPELINE_TYPE_SIZE]; - - uint32_t socket_id; - uint32_t core_id; - uint32_t hyper_th_id; - - struct app_pktq_in_params pktq_in[APP_MAX_PIPELINE_PKTQ_IN]; - struct app_pktq_out_params pktq_out[APP_MAX_PIPELINE_PKTQ_OUT]; - uint32_t msgq_in[APP_MAX_PIPELINE_MSGQ_IN]; - uint32_t msgq_out[APP_MAX_PIPELINE_MSGQ_OUT]; - - uint32_t n_pktq_in; - uint32_t n_pktq_out; - uint32_t n_msgq_in; - uint32_t n_msgq_out; - - uint32_t timer_period; - - char *args_name[APP_MAX_PIPELINE_ARGS]; - char *args_value[APP_MAX_PIPELINE_ARGS]; - uint32_t n_args; -}; - -struct app_params; - -typedef void (*app_link_op)(struct app_params *app, - uint32_t link_id, - uint32_t up, - void *arg); - -#ifndef APP_MAX_PIPELINES -#define APP_MAX_PIPELINES 64 -#endif - -struct app_link_data { - app_link_op f_link[APP_MAX_PIPELINES]; - void *arg[APP_MAX_PIPELINES]; -}; - -struct app_pipeline_data { - void *be; - void *fe; - struct pipeline_type *ptype; - uint64_t timer_period; - uint32_t enabled; -}; - -struct app_thread_pipeline_data { - uint32_t pipeline_id; - void *be; - pipeline_be_op_run f_run; - pipeline_be_op_timer f_timer; - uint64_t timer_period; - uint64_t deadline; -}; - -#ifndef APP_MAX_THREAD_PIPELINES -#define APP_MAX_THREAD_PIPELINES 64 -#endif - -#ifndef APP_THREAD_TIMER_PERIOD -#define APP_THREAD_TIMER_PERIOD 1 -#endif - -struct app_thread_data { - struct app_thread_pipeline_data regular[APP_MAX_THREAD_PIPELINES]; - struct app_thread_pipeline_data custom[APP_MAX_THREAD_PIPELINES]; - - uint32_t n_regular; - uint32_t n_custom; - - uint64_t timer_period; - uint64_t thread_req_deadline; - - uint64_t deadline; - - struct rte_ring *msgq_in; - struct rte_ring *msgq_out; - - uint64_t headroom_time; - uint64_t headroom_cycles; - double headroom_ratio; -} __rte_cache_aligned; - -#ifndef APP_MAX_LINKS -#define APP_MAX_LINKS 16 -#endif - -struct app_eal_params { - /* Map lcore set to physical cpu set */ - char *coremap; - - /* Core ID that is used as master */ - uint32_t master_lcore_present; - uint32_t master_lcore; - - /* Number of memory channels */ - uint32_t channels_present; - uint32_t channels; - - /* Memory to allocate (see also --socket-mem) */ - uint32_t memory_present; - uint32_t memory; - - /* Force number of memory ranks (don't detect) */ - uint32_t ranks_present; - uint32_t ranks; - - /* Add a PCI device in black list. */ - char *pci_blacklist[APP_MAX_LINKS]; - - /* Add a PCI device in white list. */ - char *pci_whitelist[APP_MAX_LINKS]; - - /* Add a virtual device. */ - char *vdev[APP_MAX_LINKS]; - - /* Use VMware TSC map instead of native RDTSC */ - uint32_t vmware_tsc_map_present; - int vmware_tsc_map; - - /* Type of this process (primary|secondary|auto) */ - char *proc_type; - - /* Set syslog facility */ - char *syslog; - - /* Set default log level */ - uint32_t log_level_present; - uint32_t log_level; - - /* Display version information on startup */ - uint32_t version_present; - int version; - - /* This help */ - uint32_t help_present; - int help; - - /* Use malloc instead of hugetlbfs */ - uint32_t no_huge_present; - int no_huge; - - /* Disable PCI */ - uint32_t no_pci_present; - int no_pci; - - /* Disable HPET */ - uint32_t no_hpet_present; - int no_hpet; - - /* No shared config (mmap'd files) */ - uint32_t no_shconf_present; - int no_shconf; - - /* Add driver */ - char *add_driver; - - /* Memory to allocate on sockets (comma separated values)*/ - char *socket_mem; - - /* Directory where hugetlbfs is mounted */ - char *huge_dir; - - /* Prefix for hugepage filenames */ - char *file_prefix; - - /* Base virtual address */ - char *base_virtaddr; - - /* Create /dev/uioX (usually done by hotplug) */ - uint32_t create_uio_dev_present; - int create_uio_dev; - - /* Interrupt mode for VFIO (legacy|msi|msix) */ - char *vfio_intr; - - uint32_t parsed; -}; - -#ifndef APP_APPNAME_SIZE -#define APP_APPNAME_SIZE 256 -#endif - -#ifndef APP_MAX_MEMPOOLS -#define APP_MAX_MEMPOOLS 8 -#endif - -#define APP_MAX_HWQ_IN (APP_MAX_LINKS * APP_LINK_MAX_HWQ_IN) - -#define APP_MAX_HWQ_OUT (APP_MAX_LINKS * APP_LINK_MAX_HWQ_OUT) - -#ifndef APP_MAX_PKTQ_SWQ -#define APP_MAX_PKTQ_SWQ 256 -#endif - -#define APP_MAX_PKTQ_TM APP_MAX_LINKS - -#ifndef APP_MAX_PKTQ_TAP -#define APP_MAX_PKTQ_TAP APP_MAX_LINKS -#endif - -#define APP_MAX_PKTQ_KNI APP_MAX_LINKS - -#ifndef APP_MAX_PKTQ_SOURCE -#define APP_MAX_PKTQ_SOURCE 64 -#endif - -#ifndef APP_MAX_PKTQ_SINK -#define APP_MAX_PKTQ_SINK 64 -#endif - -#ifndef APP_MAX_MSGQ -#define APP_MAX_MSGQ 256 -#endif - -#ifndef APP_EAL_ARGC -#define APP_EAL_ARGC 64 -#endif - -#ifndef APP_MAX_PIPELINE_TYPES -#define APP_MAX_PIPELINE_TYPES 64 -#endif - -#ifndef APP_MAX_THREADS -#define APP_MAX_THREADS RTE_MAX_LCORE -#endif - -#ifndef APP_MAX_CMDS -#define APP_MAX_CMDS 64 -#endif - -#ifndef APP_THREAD_HEADROOM_STATS_COLLECT -#define APP_THREAD_HEADROOM_STATS_COLLECT 1 -#endif - -#define APP_CORE_MASK_SIZE \ - (RTE_MAX_LCORE / 64 + ((RTE_MAX_LCORE % 64) ? 1 : 0)) - -struct app_params { - /* Config */ - char app_name[APP_APPNAME_SIZE]; - const char *config_file; - const char *script_file; - const char *parser_file; - const char *output_file; - const char *preproc; - const char *preproc_args; - uint64_t port_mask; - uint32_t log_level; - - struct app_eal_params eal_params; - struct app_mempool_params mempool_params[APP_MAX_MEMPOOLS]; - struct app_link_params link_params[APP_MAX_LINKS]; - struct app_pktq_hwq_in_params hwq_in_params[APP_MAX_HWQ_IN]; - struct app_pktq_hwq_out_params hwq_out_params[APP_MAX_HWQ_OUT]; - struct app_pktq_swq_params swq_params[APP_MAX_PKTQ_SWQ]; - struct app_pktq_tm_params tm_params[APP_MAX_PKTQ_TM]; - struct app_pktq_tap_params tap_params[APP_MAX_PKTQ_TAP]; - struct app_pktq_kni_params kni_params[APP_MAX_PKTQ_KNI]; - struct app_pktq_source_params source_params[APP_MAX_PKTQ_SOURCE]; - struct app_pktq_sink_params sink_params[APP_MAX_PKTQ_SINK]; - struct app_msgq_params msgq_params[APP_MAX_MSGQ]; - struct app_pipeline_params pipeline_params[APP_MAX_PIPELINES]; - - uint32_t n_mempools; - uint32_t n_links; - uint32_t n_pktq_hwq_in; - uint32_t n_pktq_hwq_out; - uint32_t n_pktq_swq; - uint32_t n_pktq_tm; - uint32_t n_pktq_tap; - uint32_t n_pktq_kni; - uint32_t n_pktq_source; - uint32_t n_pktq_sink; - uint32_t n_msgq; - uint32_t n_pipelines; - - /* Init */ - char *eal_argv[1 + APP_EAL_ARGC]; - struct cpu_core_map *core_map; - uint64_t core_mask[APP_CORE_MASK_SIZE]; - struct rte_mempool *mempool[APP_MAX_MEMPOOLS]; - struct app_link_data link_data[APP_MAX_LINKS]; - struct rte_ring *swq[APP_MAX_PKTQ_SWQ]; - struct rte_sched_port *tm[APP_MAX_PKTQ_TM]; - int tap[APP_MAX_PKTQ_TAP]; -#ifdef RTE_LIBRTE_KNI - struct rte_kni *kni[APP_MAX_PKTQ_KNI]; -#endif /* RTE_LIBRTE_KNI */ - struct rte_ring *msgq[APP_MAX_MSGQ]; - struct pipeline_type pipeline_type[APP_MAX_PIPELINE_TYPES]; - struct app_pipeline_data pipeline_data[APP_MAX_PIPELINES]; - struct app_thread_data thread_data[APP_MAX_THREADS]; - cmdline_parse_ctx_t cmds[APP_MAX_CMDS + 1]; - - int eal_argc; - uint32_t n_pipeline_types; - uint32_t n_cmds; -}; - -#define APP_PARAM_VALID(obj) ((obj)->name != NULL) - -#define APP_PARAM_COUNT(obj_array, n_objs) \ -{ \ - size_t i; \ - \ - n_objs = 0; \ - for (i = 0; i < RTE_DIM(obj_array); i++) \ - if (APP_PARAM_VALID(&((obj_array)[i]))) \ - n_objs++; \ -} - -#define APP_PARAM_FIND(obj_array, key) \ -({ \ - ssize_t obj_idx; \ - const ssize_t obj_count = RTE_DIM(obj_array); \ - \ - for (obj_idx = 0; obj_idx < obj_count; obj_idx++) { \ - if (!APP_PARAM_VALID(&((obj_array)[obj_idx]))) \ - continue; \ - \ - if (strcmp(key, (obj_array)[obj_idx].name) == 0) \ - break; \ - } \ - obj_idx < obj_count ? obj_idx : -ENOENT; \ -}) - -#define APP_PARAM_FIND_BY_ID(obj_array, prefix, id, obj) \ -do { \ - char name[APP_PARAM_NAME_SIZE]; \ - ssize_t pos; \ - \ - sprintf(name, prefix "%" PRIu32, id); \ - pos = APP_PARAM_FIND(obj_array, name); \ - obj = (pos < 0) ? NULL : &((obj_array)[pos]); \ -} while (0) - -#define APP_PARAM_GET_ID(obj, prefix, id) \ -do \ - sscanf(obj->name, prefix "%" SCNu32, &id); \ -while (0) \ - -#define APP_CHECK(exp, fmt, ...) \ -do { \ - if (!(exp)) { \ - fprintf(stderr, fmt "\n", ## __VA_ARGS__); \ - abort(); \ - } \ -} while (0) - -enum app_log_level { - APP_LOG_LEVEL_HIGH = 1, - APP_LOG_LEVEL_LOW, - APP_LOG_LEVELS -}; - -#define APP_LOG(app, level, fmt, ...) \ -do { \ - if (app->log_level >= APP_LOG_LEVEL_ ## level) \ - fprintf(stdout, "[APP] " fmt "\n", ## __VA_ARGS__); \ -} while (0) - -static inline uint32_t -app_link_get_n_rxq(struct app_params *app, struct app_link_params *link) -{ - uint32_t n_rxq = 0, link_id, i; - uint32_t n_pktq_hwq_in = RTE_MIN(app->n_pktq_hwq_in, - RTE_DIM(app->hwq_in_params)); - - APP_PARAM_GET_ID(link, "LINK", link_id); - - for (i = 0; i < n_pktq_hwq_in; i++) { - struct app_pktq_hwq_in_params *p = &app->hwq_in_params[i]; - uint32_t rxq_link_id, rxq_queue_id; - - sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32, - &rxq_link_id, &rxq_queue_id); - if (rxq_link_id == link_id) - n_rxq++; - } - - return n_rxq; -} - -static inline uint32_t -app_link_get_n_txq(struct app_params *app, struct app_link_params *link) -{ - uint32_t n_txq = 0, link_id, i; - uint32_t n_pktq_hwq_out = RTE_MIN(app->n_pktq_hwq_out, - RTE_DIM(app->hwq_out_params)); - - APP_PARAM_GET_ID(link, "LINK", link_id); - - for (i = 0; i < n_pktq_hwq_out; i++) { - struct app_pktq_hwq_out_params *p = &app->hwq_out_params[i]; - uint32_t txq_link_id, txq_queue_id; - - sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32, - &txq_link_id, &txq_queue_id); - if (txq_link_id == link_id) - n_txq++; - } - - return n_txq; -} - -static inline uint32_t -app_rxq_get_readers(struct app_params *app, struct app_pktq_hwq_in_params *rxq) -{ - uint32_t pos = rxq - app->hwq_in_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_HWQ) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline uint32_t -app_swq_get_readers(struct app_params *app, struct app_pktq_swq_params *swq) -{ - uint32_t pos = swq - app->swq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_SWQ) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline struct app_pipeline_params * -app_swq_get_reader(struct app_params *app, - struct app_pktq_swq_params *swq, - uint32_t *pktq_in_id) -{ - struct app_pipeline_params *reader = NULL; - uint32_t pos = swq - app->swq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_SWQ) && - (pktq->id == pos)) { - n_readers++; - reader = p; - id = j; - } - } - } - - if (n_readers != 1) - return NULL; - - *pktq_in_id = id; - return reader; -} - -static inline uint32_t -app_tm_get_readers(struct app_params *app, struct app_pktq_tm_params *tm) -{ - uint32_t pos = tm - app->tm_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_TM) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline struct app_pipeline_params * -app_tm_get_reader(struct app_params *app, - struct app_pktq_tm_params *tm, - uint32_t *pktq_in_id) -{ - struct app_pipeline_params *reader = NULL; - uint32_t pos = tm - app->tm_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_TM) && - (pktq->id == pos)) { - n_readers++; - reader = p; - id = j; - } - } - } - - if (n_readers != 1) - return NULL; - - *pktq_in_id = id; - return reader; -} - -static inline uint32_t -app_tap_get_readers(struct app_params *app, struct app_pktq_tap_params *tap) -{ - uint32_t pos = tap - app->tap_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_TAP) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline struct app_pipeline_params * -app_tap_get_reader(struct app_params *app, - struct app_pktq_tap_params *tap, - uint32_t *pktq_in_id) -{ - struct app_pipeline_params *reader = NULL; - uint32_t pos = tap - app->tap_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_TAP) && - (pktq->id == pos)) { - n_readers++; - reader = p; - id = j; - } - } - } - - if (n_readers != 1) - return NULL; - - *pktq_in_id = id; - return reader; -} - -static inline uint32_t -app_kni_get_readers(struct app_params *app, struct app_pktq_kni_params *kni) -{ - uint32_t pos = kni - app->kni_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_KNI) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline struct app_pipeline_params * -app_kni_get_reader(struct app_params *app, - struct app_pktq_kni_params *kni, - uint32_t *pktq_in_id) -{ - struct app_pipeline_params *reader = NULL; - uint32_t pos = kni - app->kni_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_KNI) && - (pktq->id == pos)) { - n_readers++; - reader = p; - id = j; - } - } - } - - if (n_readers != 1) - return NULL; - - *pktq_in_id = id; - return reader; -} - -static inline uint32_t -app_source_get_readers(struct app_params *app, -struct app_pktq_source_params *source) -{ - uint32_t pos = source - app->source_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_in = RTE_MIN(p->n_pktq_in, RTE_DIM(p->pktq_in)); - uint32_t j; - - for (j = 0; j < n_pktq_in; j++) { - struct app_pktq_in_params *pktq = &p->pktq_in[j]; - - if ((pktq->type == APP_PKTQ_IN_SOURCE) && - (pktq->id == pos)) - n_readers++; - } - } - - return n_readers; -} - -static inline uint32_t -app_msgq_get_readers(struct app_params *app, struct app_msgq_params *msgq) -{ - uint32_t pos = msgq - app->msgq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_readers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_msgq_in = RTE_MIN(p->n_msgq_in, RTE_DIM(p->msgq_in)); - uint32_t j; - - for (j = 0; j < n_msgq_in; j++) - if (p->msgq_in[j] == pos) - n_readers++; - } - - return n_readers; -} - -static inline uint32_t -app_txq_get_writers(struct app_params *app, struct app_pktq_hwq_out_params *txq) -{ - uint32_t pos = txq - app->hwq_out_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_HWQ) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline uint32_t -app_swq_get_writers(struct app_params *app, struct app_pktq_swq_params *swq) -{ - uint32_t pos = swq - app->swq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_SWQ) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline struct app_pipeline_params * -app_swq_get_writer(struct app_params *app, - struct app_pktq_swq_params *swq, - uint32_t *pktq_out_id) -{ - struct app_pipeline_params *writer = NULL; - uint32_t pos = swq - app->swq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_SWQ) && - (pktq->id == pos)) { - n_writers++; - writer = p; - id = j; - } - } - } - - if (n_writers != 1) - return NULL; - - *pktq_out_id = id; - return writer; -} - -static inline uint32_t -app_tm_get_writers(struct app_params *app, struct app_pktq_tm_params *tm) -{ - uint32_t pos = tm - app->tm_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_TM) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline struct app_pipeline_params * -app_tm_get_writer(struct app_params *app, - struct app_pktq_tm_params *tm, - uint32_t *pktq_out_id) -{ - struct app_pipeline_params *writer = NULL; - uint32_t pos = tm - app->tm_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_TM) && - (pktq->id == pos)) { - n_writers++; - writer = p; - id = j; - } - } - } - - if (n_writers != 1) - return NULL; - - *pktq_out_id = id; - return writer; -} - -static inline uint32_t -app_tap_get_writers(struct app_params *app, struct app_pktq_tap_params *tap) -{ - uint32_t pos = tap - app->tap_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_TAP) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline struct app_pipeline_params * -app_tap_get_writer(struct app_params *app, - struct app_pktq_tap_params *tap, - uint32_t *pktq_out_id) -{ - struct app_pipeline_params *writer = NULL; - uint32_t pos = tap - app->tap_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_TAP) && - (pktq->id == pos)) { - n_writers++; - writer = p; - id = j; - } - } - } - - if (n_writers != 1) - return NULL; - - *pktq_out_id = id; - return writer; -} - -static inline uint32_t -app_kni_get_writers(struct app_params *app, struct app_pktq_kni_params *kni) -{ - uint32_t pos = kni - app->kni_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_KNI) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline struct app_pipeline_params * -app_kni_get_writer(struct app_params *app, - struct app_pktq_kni_params *kni, - uint32_t *pktq_out_id) -{ - struct app_pipeline_params *writer = NULL; - uint32_t pos = kni - app->kni_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, id = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_KNI) && - (pktq->id == pos)) { - n_writers++; - writer = p; - id = j; - } - } - } - - if (n_writers != 1) - return NULL; - - *pktq_out_id = id; - return writer; -} - -static inline uint32_t -app_sink_get_writers(struct app_params *app, struct app_pktq_sink_params *sink) -{ - uint32_t pos = sink - app->sink_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_pktq_out = RTE_MIN(p->n_pktq_out, - RTE_DIM(p->pktq_out)); - uint32_t j; - - for (j = 0; j < n_pktq_out; j++) { - struct app_pktq_out_params *pktq = &p->pktq_out[j]; - - if ((pktq->type == APP_PKTQ_OUT_SINK) && - (pktq->id == pos)) - n_writers++; - } - } - - return n_writers; -} - -static inline uint32_t -app_msgq_get_writers(struct app_params *app, struct app_msgq_params *msgq) -{ - uint32_t pos = msgq - app->msgq_params; - uint32_t n_pipelines = RTE_MIN(app->n_pipelines, - RTE_DIM(app->pipeline_params)); - uint32_t n_writers = 0, i; - - for (i = 0; i < n_pipelines; i++) { - struct app_pipeline_params *p = &app->pipeline_params[i]; - uint32_t n_msgq_out = RTE_MIN(p->n_msgq_out, - RTE_DIM(p->msgq_out)); - uint32_t j; - - for (j = 0; j < n_msgq_out; j++) - if (p->msgq_out[j] == pos) - n_writers++; - } - - return n_writers; -} - -static inline struct app_link_params * -app_get_link_for_rxq(struct app_params *app, struct app_pktq_hwq_in_params *p) -{ - char link_name[APP_PARAM_NAME_SIZE]; - ssize_t link_param_idx; - uint32_t rxq_link_id, rxq_queue_id; - - sscanf(p->name, "RXQ%" SCNu32 ".%" SCNu32, - &rxq_link_id, &rxq_queue_id); - sprintf(link_name, "LINK%" PRIu32, rxq_link_id); - link_param_idx = APP_PARAM_FIND(app->link_params, link_name); - APP_CHECK((link_param_idx >= 0), - "Cannot find %s for %s", link_name, p->name); - - return &app->link_params[link_param_idx]; -} - -static inline struct app_link_params * -app_get_link_for_txq(struct app_params *app, struct app_pktq_hwq_out_params *p) -{ - char link_name[APP_PARAM_NAME_SIZE]; - ssize_t link_param_idx; - uint32_t txq_link_id, txq_queue_id; - - sscanf(p->name, "TXQ%" SCNu32 ".%" SCNu32, - &txq_link_id, &txq_queue_id); - sprintf(link_name, "LINK%" PRIu32, txq_link_id); - link_param_idx = APP_PARAM_FIND(app->link_params, link_name); - APP_CHECK((link_param_idx >= 0), - "Cannot find %s for %s", link_name, p->name); - - return &app->link_params[link_param_idx]; -} - -static inline struct app_link_params * -app_get_link_for_tm(struct app_params *app, struct app_pktq_tm_params *p_tm) -{ - char link_name[APP_PARAM_NAME_SIZE]; - uint32_t link_id; - ssize_t link_param_idx; - - sscanf(p_tm->name, "TM%" PRIu32, &link_id); - sprintf(link_name, "LINK%" PRIu32, link_id); - link_param_idx = APP_PARAM_FIND(app->link_params, link_name); - APP_CHECK((link_param_idx >= 0), - "Cannot find %s for %s", link_name, p_tm->name); - - return &app->link_params[link_param_idx]; -} - -static inline struct app_link_params * -app_get_link_for_kni(struct app_params *app, struct app_pktq_kni_params *p_kni) -{ - char link_name[APP_PARAM_NAME_SIZE]; - uint32_t link_id; - ssize_t link_param_idx; - - sscanf(p_kni->name, "KNI%" PRIu32, &link_id); - sprintf(link_name, "LINK%" PRIu32, link_id); - link_param_idx = APP_PARAM_FIND(app->link_params, link_name); - APP_CHECK((link_param_idx >= 0), - "Cannot find %s for %s", link_name, p_kni->name); - - return &app->link_params[link_param_idx]; -} - -static inline uint32_t -app_core_is_enabled(struct app_params *app, uint32_t lcore_id) -{ - return(app->core_mask[lcore_id / 64] & - (1LLU << (lcore_id % 64))); -} - -static inline void -app_core_enable_in_core_mask(struct app_params *app, int lcore_id) -{ - app->core_mask[lcore_id / 64] |= 1LLU << (lcore_id % 64); - -} - -static inline void -app_core_build_core_mask_string(struct app_params *app, char *mask_buffer) -{ - int i; - - mask_buffer[0] = '\0'; - for (i = (int)RTE_DIM(app->core_mask); i > 0; i--) { - /* For Hex representation of bits in uint64_t */ - char buffer[(64 / 8) * 2 + 1]; - memset(buffer, 0, sizeof(buffer)); - snprintf(buffer, sizeof(buffer), "%016" PRIx64, - app->core_mask[i-1]); - strcat(mask_buffer, buffer); - } -} - -void app_pipeline_params_get(struct app_params *app, - struct app_pipeline_params *p_in, - struct pipeline_params *p_out); - -int app_config_init(struct app_params *app); - -int app_config_args(struct app_params *app, - int argc, char **argv); - -int app_config_preproc(struct app_params *app); - -int app_config_parse(struct app_params *app, - const char *file_name); - -int app_config_parse_tm(struct app_params *app); - -void app_config_save(struct app_params *app, - const char *file_name); - -int app_config_check(struct app_params *app); - -int app_init(struct app_params *app); - -int app_post_init(struct app_params *app); - -int app_thread(void *arg); - -int app_pipeline_type_register(struct app_params *app, - struct pipeline_type *ptype); - -struct pipeline_type *app_pipeline_type_find(struct app_params *app, - char *name); - -void app_link_up_internal(struct app_params *app, - struct app_link_params *cp); - -void app_link_down_internal(struct app_params *app, - struct app_link_params *cp); - -#endif diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c new file mode 100644 index 00000000..102a1d6b --- /dev/null +++ b/examples/ip_pipeline/cli.c @@ -0,0 +1,5240 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "cli.h" +#include "kni.h" +#include "link.h" +#include "mempool.h" +#include "parser.h" +#include "pipeline.h" +#include "swq.h" +#include "tap.h" +#include "thread.h" +#include "tmgr.h" + +#ifndef CMD_MAX_TOKENS +#define CMD_MAX_TOKENS 256 +#endif + +#define MSG_OUT_OF_MEMORY "Not enough memory.\n" +#define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" +#define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" +#define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" +#define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" +#define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" +#define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" +#define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" +#define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" +#define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" +#define MSG_CMD_FAIL "Command \"%s\" failed.\n" + +static int +is_comment(char *in) +{ + if ((strlen(in) && index("!#%;", in[0])) || + (strncmp(in, "//", 2) == 0) || + (strncmp(in, "--", 2) == 0)) + return 1; + + return 0; +} + +static const char cmd_mempool_help[] = +"mempool \n" +" buffer \n" +" pool \n" +" cache \n" +" cpu \n"; + +static void +cmd_mempool(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct mempool_params p; + char *name; + struct mempool *mempool; + + if (n_tokens != 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "buffer") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); + return; + } + + if (parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); + return; + } + + if (strcmp(tokens[4], "pool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); + return; + } + + if (parser_read_uint32(&p.pool_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); + return; + } + + if (strcmp(tokens[6], "cache") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); + return; + } + + if (parser_read_uint32(&p.cache_size, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); + return; + } + + if (strcmp(tokens[8], "cpu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); + return; + } + + if (parser_read_uint32(&p.cpu_id, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); + return; + } + + mempool = mempool_create(name, &p); + if (mempool == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_link_help[] = +"link \n" +" dev | port \n" +" rxq \n" +" txq \n" +" promiscuous on | off\n" +" [rss ... ]\n"; + +static void +cmd_link(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct link_params p; + struct link_params_rss rss; + struct link *link; + char *name; + + memset(&p, 0, sizeof(p)); + + if ((n_tokens < 13) || (n_tokens > 14 + LINK_RXQ_RSS_MAX)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + name = tokens[1]; + + if (strcmp(tokens[2], "dev") == 0) + p.dev_name = tokens[3]; + else if (strcmp(tokens[2], "port") == 0) { + p.dev_name = NULL; + + if (parser_read_uint16(&p.port_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); + return; + } + + if (strcmp(tokens[4], "rxq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); + return; + } + + if (parser_read_uint32(&p.rx.n_queues, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); + return; + } + if (parser_read_uint32(&p.rx.queue_size, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); + return; + } + + p.rx.mempool_name = tokens[7]; + + if (strcmp(tokens[8], "txq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); + return; + } + + if (parser_read_uint32(&p.tx.n_queues, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_queues"); + return; + } + + if (parser_read_uint32(&p.tx.queue_size, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "queue_size"); + return; + } + + if (strcmp(tokens[11], "promiscuous") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "promiscuous"); + return; + } + + if (strcmp(tokens[12], "on") == 0) + p.promiscuous = 1; + else if (strcmp(tokens[12], "off") == 0) + p.promiscuous = 0; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "on or off"); + return; + } + + /* RSS */ + p.rx.rss = NULL; + if (n_tokens > 13) { + uint32_t queue_id, i; + + if (strcmp(tokens[13], "rss") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rss"); + return; + } + + p.rx.rss = &rss; + + rss.n_queues = 0; + for (i = 14; i < n_tokens; i++) { + if (parser_read_uint32(&queue_id, tokens[i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "queue_id"); + return; + } + + rss.queue_id[rss.n_queues] = queue_id; + rss.n_queues++; + } + } + + link = link_create(name, &p); + if (link == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +/* Print the link stats and info */ +static void +print_link_info(struct link *link, char *out, size_t out_size) +{ + struct rte_eth_stats stats; + struct ether_addr mac_addr; + struct rte_eth_link eth_link; + uint16_t mtu; + + memset(&stats, 0, sizeof(stats)); + rte_eth_stats_get(link->port_id, &stats); + + rte_eth_macaddr_get(link->port_id, &mac_addr); + rte_eth_link_get(link->port_id, ð_link); + rte_eth_dev_get_mtu(link->port_id, &mtu); + + snprintf(out, out_size, + "\n" + "%s: flags=<%s> mtu %u\n" + "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n" + "\tport# %u speed %u Mbps\n" + "\tRX packets %" PRIu64" bytes %" PRIu64"\n" + "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" + "\tTX packets %" PRIu64" bytes %" PRIu64"\n" + "\tTX errors %" PRIu64"\n", + link->name, + eth_link.link_status == 0 ? "DOWN" : "UP", + mtu, + mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], + mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], + mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], + link->n_rxq, + link->n_txq, + link->port_id, + eth_link.link_speed, + stats.ipackets, + stats.ibytes, + stats.ierrors, + stats.imissed, + stats.rx_nombuf, + stats.opackets, + stats.obytes, + stats.oerrors); +} + +/* + * link show [] + */ +static void +cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size) +{ + struct link *link; + char *link_name; + + if (n_tokens != 2 && n_tokens != 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (n_tokens == 2) { + link = link_next(NULL); + + while (link != NULL) { + out_size = out_size - strlen(out); + out = &out[strlen(out)]; + + print_link_info(link, out, out_size); + link = link_next(link); + } + } else { + out_size = out_size - strlen(out); + out = &out[strlen(out)]; + + link_name = tokens[2]; + link = link_find(link_name); + + if (link == NULL) { + snprintf(out, out_size, MSG_ARG_INVALID, + "Link does not exist"); + return; + } + print_link_info(link, out, out_size); + } +} + +static const char cmd_swq_help[] = +"swq \n" +" size \n" +" cpu \n"; + +static void +cmd_swq(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct swq_params p; + char *name; + struct swq *swq; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (parser_read_uint32(&p.size, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "size"); + return; + } + + if (strcmp(tokens[4], "cpu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); + return; + } + + if (parser_read_uint32(&p.cpu_id, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); + return; + } + + swq = swq_create(name, &p); + if (swq == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_tmgr_subport_profile_help[] = +"tmgr subport profile\n" +" \n" +" \n" +" \n"; + +static void +cmd_tmgr_subport_profile(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_sched_subport_params p; + int status, i; + + if (n_tokens != 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); + return; + } + + if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); + return; + } + + if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); + return; + } + + status = tmgr_subport_profile_add(&p); + if (status != 0) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_tmgr_pipe_profile_help[] = +"tmgr pipe profile\n" +" \n" +" \n" +" \n" +" \n" +" \n"; + +static void +cmd_tmgr_pipe_profile(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_sched_pipe_params p; + int status, i; + + if (n_tokens != 27) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (parser_read_uint32(&p.tb_rate, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); + return; + } + + if (parser_read_uint32(&p.tb_size, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint32(&p.tc_rate[i], tokens[5 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tc_rate"); + return; + } + + if (parser_read_uint32(&p.tc_period, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tc_period"); + return; + } + +#ifdef RTE_SCHED_SUBPORT_TC_OV + if (parser_read_uint8(&p.tc_ov_weight, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "tc_ov_weight"); + return; + } +#endif + + for (i = 0; i < RTE_SCHED_QUEUES_PER_PIPE; i++) + if (parser_read_uint8(&p.wrr_weights[i], tokens[11 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "wrr_weights"); + return; + } + + status = tmgr_pipe_profile_add(&p); + if (status != 0) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_tmgr_help[] = +"tmgr \n" +" rate \n" +" spp \n" +" pps \n" +" qsize \n" +" fo \n" +" mtu \n" +" cpu \n"; + +static void +cmd_tmgr(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct tmgr_port_params p; + char *name; + struct tmgr_port *tmgr_port; + int i; + + if (n_tokens != 19) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "rate") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate"); + return; + } + + if (parser_read_uint32(&p.rate, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "rate"); + return; + } + + if (strcmp(tokens[4], "spp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); + return; + } + + if (parser_read_uint32(&p.n_subports_per_port, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port"); + return; + } + + if (strcmp(tokens[6], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.n_pipes_per_subport, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); + return; + } + + if (strcmp(tokens[8], "qsize") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "qsize"); + return; + } + + for (i = 0; i < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; i++) + if (parser_read_uint16(&p.qsize[i], tokens[9 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "qsize"); + return; + } + + if (strcmp(tokens[13], "fo") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fo"); + return; + } + + if (parser_read_uint32(&p.frame_overhead, tokens[14]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "frame_overhead"); + return; + } + + if (strcmp(tokens[15], "mtu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mtu"); + return; + } + + if (parser_read_uint32(&p.mtu, tokens[16]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); + return; + } + + if (strcmp(tokens[17], "cpu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); + return; + } + + if (parser_read_uint32(&p.cpu_id, tokens[18]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); + return; + } + + tmgr_port = tmgr_port_create(name, &p); + if (tmgr_port == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_tmgr_subport_help[] = +"tmgr subport \n" +" profile \n"; + +static void +cmd_tmgr_subport(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + uint32_t subport_id, subport_profile_id; + int status; + char *name; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (parser_read_uint32(&subport_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); + return; + } + + if (parser_read_uint32(&subport_profile_id, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "subport_profile_id"); + return; + } + + status = tmgr_subport_config(name, subport_id, subport_profile_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_tmgr_subport_pipe_help[] = +"tmgr subport pipe\n" +" from to \n" +" profile \n"; + +static void +cmd_tmgr_subport_pipe(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + uint32_t subport_id, pipe_id_first, pipe_id_last, pipe_profile_id; + int status; + char *name; + + if (n_tokens != 11) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (parser_read_uint32(&subport_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "subport_id"); + return; + } + + if (strcmp(tokens[4], "pipe") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe"); + return; + } + + if (strcmp(tokens[5], "from") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "from"); + return; + } + + if (parser_read_uint32(&pipe_id_first, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_first"); + return; + } + + if (strcmp(tokens[7], "to") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "to"); + return; + } + + if (parser_read_uint32(&pipe_id_last, tokens[8]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipe_id_last"); + return; + } + + if (strcmp(tokens[9], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + if (parser_read_uint32(&pipe_profile_id, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id"); + return; + } + + status = tmgr_pipe_config(name, subport_id, pipe_id_first, + pipe_id_last, pipe_profile_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_tap_help[] = +"tap \n"; + +static void +cmd_tap(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *name; + struct tap *tap; + + if (n_tokens != 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + tap = tap_create(name); + if (tap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_kni_help[] = +"kni \n" +" link \n" +" mempool \n" +" [thread ]\n"; + +static void +cmd_kni(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct kni_params p; + char *name; + struct kni *kni; + + memset(&p, 0, sizeof(p)); + if ((n_tokens != 6) && (n_tokens != 8)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "link") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "link"); + return; + } + + p.link_name = tokens[3]; + + if (strcmp(tokens[4], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mempool"); + return; + } + + p.mempool_name = tokens[5]; + + if (n_tokens == 8) { + if (strcmp(tokens[6], "thread") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "thread"); + return; + } + + if (parser_read_uint32(&p.thread_id, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); + return; + } + + p.force_bind = 1; + } else + p.force_bind = 0; + + kni = kni_create(name, &p); + if (kni == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_port_in_action_profile_help[] = +"port in action profile \n" +" [filter match | mismatch offset mask key port ]\n" +" [balance offset mask port ... ]\n"; + +static void +cmd_port_in_action_profile(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_in_action_profile_params p; + struct port_in_action_profile *ap; + char *name; + uint32_t t0; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (strcmp(tokens[2], "action") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); + return; + } + + if (strcmp(tokens[3], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + name = tokens[4]; + + t0 = 5; + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "filter") == 0)) { + uint32_t size; + + if (n_tokens < t0 + 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); + return; + } + + if (strcmp(tokens[t0 + 1], "match") == 0) + p.fltr.filter_on_match = 1; + else if (strcmp(tokens[t0 + 1], "mismatch") == 0) + p.fltr.filter_on_match = 0; + else { + snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.fltr.key_offset, tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; + if ((parse_hex_string(tokens[t0 + 5], p.fltr.key_mask, &size) != 0) || + (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 6], "key") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); + return; + } + + size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; + if ((parse_hex_string(tokens[t0 + 7], p.fltr.key, &size) != 0) || + (size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE)) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); + return; + } + + if (strcmp(tokens[t0 + 8], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (parser_read_uint32(&p.fltr.port_id, tokens[t0 + 9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; + t0 += 10; + } /* filter */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { + uint32_t i; + + if (n_tokens < t0 + 22) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "port in action profile balance"); + return; + } + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; + if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 5], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + for (i = 0; i < 16; i++) + if (parser_read_uint32(&p.lb.port_id[i], tokens[t0 + 6 + i]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; + t0 += 22; + } /* balance */ + + if (t0 < n_tokens) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ap = port_in_action_profile_create(name, &p); + if (ap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_table_action_profile_help[] = +"table action profile \n" +" ipv4 | ipv6\n" +" offset \n" +" fwd\n" +" [balance offset mask outoffset ]\n" +" [meter srtcm | trtcm\n" +" tc \n" +" stats none | pkts | bytes | both]\n" +" [tm spp pps ]\n" +" [encap ether | vlan | qinq | mpls | pppoe]\n" +" [nat src | dst\n" +" proto udp | tcp]\n" +" [ttl drop | fwd\n" +" stats none | pkts]\n" +" [stats pkts | bytes | both]\n" +" [time]\n"; + +static void +cmd_table_action_profile(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct table_action_profile_params p; + struct table_action_profile *ap; + char *name; + uint32_t t0; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (strcmp(tokens[1], "action") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); + return; + } + + if (strcmp(tokens[2], "profile") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); + return; + } + + name = tokens[3]; + + if (strcmp(tokens[4], "ipv4") == 0) + p.common.ip_version = 1; + else if (strcmp(tokens[4], "ipv6") == 0) + p.common.ip_version = 0; + else { + snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[5], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.common.ip_offset, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); + return; + } + + if (strcmp(tokens[7], "fwd") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; + + t0 = 8; + if ((t0 < n_tokens) && (strcmp(tokens[t0], "balance") == 0)) { + if (n_tokens < t0 + 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); + return; + } + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.lb.key_offset, tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; + if (parse_hex_string(tokens[t0 + 4], p.lb.key_mask, &p.lb.key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + + if (strcmp(tokens[t0 + 5], "outoffset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); + return; + } + + if (parser_read_uint32(&p.lb.out_offset, tokens[t0 + 6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; + t0 += 7; + } /* balance */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "meter") == 0)) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile meter"); + return; + } + + if (strcmp(tokens[t0 + 1], "srtcm") == 0) + p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; + else if (strcmp(tokens[t0 + 1], "trtcm") == 0) + p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "srtcm or trtcm"); + return; + } + + if (strcmp(tokens[t0 + 2], "tc") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); + return; + } + + if (parser_read_uint32(&p.mtr.n_tc, tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); + return; + } + + if (strcmp(tokens[t0 + 4], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[t0 + 5], "none") == 0) { + p.mtr.n_packets_enabled = 0; + p.mtr.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { + p.mtr.n_packets_enabled = 1; + p.mtr.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { + p.mtr.n_packets_enabled = 0; + p.mtr.n_bytes_enabled = 1; + } else if (strcmp(tokens[t0 + 5], "both") == 0) { + p.mtr.n_packets_enabled = 1; + p.mtr.n_bytes_enabled = 1; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "none or pkts or bytes or both"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; + t0 += 6; + } /* meter */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "tm") == 0)) { + if (n_tokens < t0 + 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile tm"); + return; + } + + if (strcmp(tokens[t0 + 1], "spp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); + return; + } + + if (parser_read_uint32(&p.tm.n_subports_per_port, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_subports_per_port"); + return; + } + + if (strcmp(tokens[t0 + 3], "pps") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); + return; + } + + if (parser_read_uint32(&p.tm.n_pipes_per_subport, + tokens[t0 + 4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_pipes_per_subport"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; + t0 += 5; + } /* tm */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "encap") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "action profile encap"); + return; + } + + if (strcmp(tokens[t0 + 1], "ether") == 0) + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; + else if (strcmp(tokens[t0 + 1], "vlan") == 0) + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; + else if (strcmp(tokens[t0 + 1], "qinq") == 0) + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; + else if (strcmp(tokens[t0 + 1], "mpls") == 0) + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; + else if (strcmp(tokens[t0 + 1], "pppoe") == 0) + p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; + else { + snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; + t0 += 2; + } /* encap */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "nat") == 0)) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile nat"); + return; + } + + if (strcmp(tokens[t0 + 1], "src") == 0) + p.nat.source_nat = 1; + else if (strcmp(tokens[t0 + 1], "dst") == 0) + p.nat.source_nat = 0; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "src or dst"); + return; + } + + if (strcmp(tokens[t0 + 2], "proto") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); + return; + } + + if (strcmp(tokens[t0 + 3], "tcp") == 0) + p.nat.proto = 0x06; + else if (strcmp(tokens[t0 + 3], "udp") == 0) + p.nat.proto = 0x11; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "tcp or udp"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; + t0 += 4; + } /* nat */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "ttl") == 0)) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile ttl"); + return; + } + + if (strcmp(tokens[t0 + 1], "drop") == 0) + p.ttl.drop = 1; + else if (strcmp(tokens[t0 + 1], "fwd") == 0) + p.ttl.drop = 0; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "drop or fwd"); + return; + } + + if (strcmp(tokens[t0 + 2], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[t0 + 3], "none") == 0) + p.ttl.n_packets_enabled = 0; + else if (strcmp(tokens[t0 + 3], "pkts") == 0) + p.ttl.n_packets_enabled = 1; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "none or pkts"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; + t0 += 4; + } /* ttl */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "stats") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "table action profile stats"); + return; + } + + if (strcmp(tokens[t0 + 1], "pkts") == 0) { + p.stats.n_packets_enabled = 1; + p.stats.n_bytes_enabled = 0; + } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { + p.stats.n_packets_enabled = 0; + p.stats.n_bytes_enabled = 1; + } else if (strcmp(tokens[t0 + 1], "both") == 0) { + p.stats.n_packets_enabled = 1; + p.stats.n_bytes_enabled = 1; + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "pkts or bytes or both"); + return; + } + + p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; + t0 += 2; + } /* stats */ + + if ((t0 < n_tokens) && (strcmp(tokens[t0], "time") == 0)) { + p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; + t0 += 1; + } /* time */ + + if (t0 < n_tokens) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + ap = table_action_profile_create(name, &p); + if (ap == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_pipeline_help[] = +"pipeline \n" +" period \n" +" offset_port_id \n" +" cpu \n"; + +static void +cmd_pipeline(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct pipeline_params p; + char *name; + struct pipeline *pipeline; + + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + name = tokens[1]; + + if (strcmp(tokens[2], "period") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); + return; + } + + if (parser_read_uint32(&p.timer_period_ms, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); + return; + } + + if (strcmp(tokens[4], "offset_port_id") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); + return; + } + + if (parser_read_uint32(&p.offset_port_id, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); + return; + } + + if (strcmp(tokens[6], "cpu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cpu"); + return; + } + + if (parser_read_uint32(&p.cpu_id, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "cpu_id"); + return; + } + + pipeline = pipeline_create(name, &p); + if (pipeline == NULL) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_pipeline_port_in_help[] = +"pipeline port in\n" +" bsz \n" +" link rxq \n" +" | swq \n" +" | tmgr \n" +" | tap mempool mtu \n" +" | kni \n" +" | source mempool file bpp \n" +" [action ]\n" +" [disabled]\n"; + +static void +cmd_pipeline_port_in(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_in_params p; + char *pipeline_name; + uint32_t t0; + int enabled, status; + + if (n_tokens < 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (strcmp(tokens[4], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); + return; + } + + t0 = 6; + + if (strcmp(tokens[t0], "link") == 0) { + if (n_tokens < t0 + 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in link"); + return; + } + + p.type = PORT_IN_RXQ; + + p.dev_name = tokens[t0 + 1]; + + if (strcmp(tokens[t0 + 2], "rxq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); + return; + } + + if (parser_read_uint16(&p.rxq.queue_id, tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "queue_id"); + return; + } + t0 += 4; + } else if (strcmp(tokens[t0], "swq") == 0) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in swq"); + return; + } + + p.type = PORT_IN_SWQ; + + p.dev_name = tokens[t0 + 1]; + + t0 += 2; + } else if (strcmp(tokens[t0], "tmgr") == 0) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in tmgr"); + return; + } + + p.type = PORT_IN_TMGR; + + p.dev_name = tokens[t0 + 1]; + + t0 += 2; + } else if (strcmp(tokens[t0], "tap") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in tap"); + return; + } + + p.type = PORT_IN_TAP; + + p.dev_name = tokens[t0 + 1]; + + if (strcmp(tokens[t0 + 2], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mempool"); + return; + } + + p.tap.mempool_name = tokens[t0 + 3]; + + if (strcmp(tokens[t0 + 4], "mtu") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mtu"); + return; + } + + if (parser_read_uint32(&p.tap.mtu, tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "kni") == 0) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in kni"); + return; + } + + p.type = PORT_IN_KNI; + + p.dev_name = tokens[t0 + 1]; + + t0 += 2; + } else if (strcmp(tokens[t0], "source") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port in source"); + return; + } + + p.type = PORT_IN_SOURCE; + + p.dev_name = NULL; + + if (strcmp(tokens[t0 + 1], "mempool") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "mempool"); + return; + } + + p.source.mempool_name = tokens[t0 + 2]; + + if (strcmp(tokens[t0 + 3], "file") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "file"); + return; + } + + p.source.file_name = tokens[t0 + 4]; + + if (strcmp(tokens[t0 + 5], "bpp") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "bpp"); + return; + } + + if (parser_read_uint32(&p.source.n_bytes_per_pkt, tokens[t0 + 6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "n_bytes_per_pkt"); + return; + } + + t0 += 7; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + p.action_profile_name = NULL; + if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); + return; + } + + p.action_profile_name = tokens[t0 + 1]; + + t0 += 2; + } + + enabled = 1; + if ((n_tokens > t0) && + (strcmp(tokens[t0], "disabled") == 0)) { + enabled = 0; + + t0 += 1; + } + + if (n_tokens != t0) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_port_in_create(pipeline_name, + &p, enabled); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_pipeline_port_out_help[] = +"pipeline port out\n" +" bsz \n" +" link txq \n" +" | swq \n" +" | tmgr \n" +" | tap \n" +" | kni \n" +" | sink [file pkts ]\n"; + +static void +cmd_pipeline_port_out(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct port_out_params p; + char *pipeline_name; + int status; + + memset(&p, 0, sizeof(p)); + + if (n_tokens < 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "out") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); + return; + } + + if (strcmp(tokens[4], "bsz") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); + return; + } + + if (parser_read_uint32(&p.burst_size, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); + return; + } + + if (strcmp(tokens[6], "link") == 0) { + if (n_tokens != 10) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out link"); + return; + } + + p.type = PORT_OUT_TXQ; + + p.dev_name = tokens[7]; + + if (strcmp(tokens[8], "txq") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); + return; + } + + if (parser_read_uint16(&p.txq.queue_id, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); + return; + } + } else if (strcmp(tokens[6], "swq") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out swq"); + return; + } + + p.type = PORT_OUT_SWQ; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "tmgr") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out tmgr"); + return; + } + + p.type = PORT_OUT_TMGR; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "tap") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out tap"); + return; + } + + p.type = PORT_OUT_TAP; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "kni") == 0) { + if (n_tokens != 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out kni"); + return; + } + + p.type = PORT_OUT_KNI; + + p.dev_name = tokens[7]; + } else if (strcmp(tokens[6], "sink") == 0) { + if ((n_tokens != 7) && (n_tokens != 11)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline port out sink"); + return; + } + + p.type = PORT_OUT_SINK; + + p.dev_name = NULL; + + if (n_tokens == 7) { + p.sink.file_name = NULL; + p.sink.max_n_pkts = 0; + } else { + if (strcmp(tokens[7], "file") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "file"); + return; + } + + p.sink.file_name = tokens[8]; + + if (strcmp(tokens[9], "pkts") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); + return; + } + + if (parser_read_uint32(&p.sink.max_n_pkts, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); + return; + } + } + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + status = pipeline_port_out_create(pipeline_name, &p); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_pipeline_table_help[] = +"pipeline table\n" +" match\n" +" acl\n" +" ipv4 | ipv6\n" +" offset \n" +" size \n" +" | array\n" +" offset \n" +" size \n" +" | hash\n" +" ext | lru\n" +" key \n" +" mask \n" +" offset \n" +" buckets \n" +" size \n" +" | lpm\n" +" ipv4 | ipv6\n" +" offset \n" +" size \n" +" | stub\n" +" [action ]\n"; + +static void +cmd_pipeline_table(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; + struct table_params p; + char *pipeline_name; + uint32_t t0; + int status; + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "table") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); + return; + } + + if (strcmp(tokens[3], "match") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); + return; + } + + t0 = 4; + if (strcmp(tokens[t0], "acl") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table acl"); + return; + } + + p.match_type = TABLE_ACL; + + if (strcmp(tokens[t0 + 1], "ipv4") == 0) + p.match.acl.ip_version = 1; + else if (strcmp(tokens[t0 + 1], "ipv6") == 0) + p.match.acl.ip_version = 0; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.match.acl.ip_header_offset, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "ip_header_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (parser_read_uint32(&p.match.acl.n_rules, + tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "array") == 0) { + if (n_tokens < t0 + 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table array"); + return; + } + + p.match_type = TABLE_ARRAY; + + if (strcmp(tokens[t0 + 1], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.match.array.key_offset, + tokens[t0 + 2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 3], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (parser_read_uint32(&p.match.array.n_keys, + tokens[t0 + 4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); + return; + } + + t0 += 5; + } else if (strcmp(tokens[t0], "hash") == 0) { + uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; + + if (n_tokens < t0 + 12) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table hash"); + return; + } + + p.match_type = TABLE_HASH; + + if (strcmp(tokens[t0 + 1], "ext") == 0) + p.match.hash.extendable_bucket = 1; + else if (strcmp(tokens[t0 + 1], "lru") == 0) + p.match.hash.extendable_bucket = 0; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ext or lru"); + return; + } + + if (strcmp(tokens[t0 + 2], "key") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); + return; + } + + if ((parser_read_uint32(&p.match.hash.key_size, + tokens[t0 + 3]) != 0) || + (p.match.hash.key_size == 0) || + (p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX)) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); + return; + } + + if (strcmp(tokens[t0 + 4], "mask") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); + return; + } + + if ((parse_hex_string(tokens[t0 + 5], + key_mask, &key_mask_size) != 0) || + (key_mask_size != p.match.hash.key_size)) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); + return; + } + p.match.hash.key_mask = key_mask; + + if (strcmp(tokens[t0 + 6], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.match.hash.key_offset, + tokens[t0 + 7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 8], "buckets") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); + return; + } + + if (parser_read_uint32(&p.match.hash.n_buckets, + tokens[t0 + 9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); + return; + } + + if (strcmp(tokens[t0 + 10], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (parser_read_uint32(&p.match.hash.n_keys, + tokens[t0 + 11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); + return; + } + + t0 += 12; + } else if (strcmp(tokens[t0], "lpm") == 0) { + if (n_tokens < t0 + 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "pipeline table lpm"); + return; + } + + p.match_type = TABLE_LPM; + + if (strcmp(tokens[t0 + 1], "ipv4") == 0) + p.match.lpm.key_size = 4; + else if (strcmp(tokens[t0 + 1], "ipv6") == 0) + p.match.lpm.key_size = 16; + else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return; + } + + if (strcmp(tokens[t0 + 2], "offset") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); + return; + } + + if (parser_read_uint32(&p.match.lpm.key_offset, + tokens[t0 + 3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); + return; + } + + if (strcmp(tokens[t0 + 4], "size") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); + return; + } + + if (parser_read_uint32(&p.match.lpm.n_rules, + tokens[t0 + 5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); + return; + } + + t0 += 6; + } else if (strcmp(tokens[t0], "stub") == 0) { + p.match_type = TABLE_STUB; + + t0 += 1; + } else { + snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); + return; + } + + p.action_profile_name = NULL; + if ((n_tokens > t0) && (strcmp(tokens[t0], "action") == 0)) { + if (n_tokens < t0 + 2) { + snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); + return; + } + + p.action_profile_name = tokens[t0 + 1]; + + t0 += 2; + } + + if (n_tokens > t0) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + status = pipeline_table_create(pipeline_name, &p); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + +static const char cmd_pipeline_port_in_table_help[] = +"pipeline port in table \n"; + +static void +cmd_pipeline_port_in_table(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id, table_id; + int status; + + if (n_tokens != 7) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "table") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); + return; + } + + if (parser_read_uint32(&table_id, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + status = pipeline_port_in_connect_to_table(pipeline_name, + port_id, + table_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_port_in_stats_help[] = +"pipeline port in stats read [clear]\n"; + +#define MSG_PIPELINE_PORT_IN_STATS \ + "Pkts in: %" PRIu64 "\n" \ + "Pkts dropped by AH: %" PRIu64 "\n" \ + "Pkts dropped by other: %" PRIu64 "\n" + +static void +cmd_pipeline_port_in_stats(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_pipeline_port_in_stats stats; + char *pipeline_name; + uint32_t port_id; + int clear, status; + + if ((n_tokens != 7) && (n_tokens != 8)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[6], "read") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); + return; + } + + clear = 0; + if (n_tokens == 8) { + if (strcmp(tokens[7], "clear") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "clear"); + return; + } + + clear = 1; + } + + status = pipeline_port_in_stats_read(pipeline_name, + port_id, + &stats, + clear); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } + + snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS, + stats.stats.n_pkts_in, + stats.n_pkts_dropped_by_ah, + stats.stats.n_pkts_drop); +} + + +static const char cmd_pipeline_port_in_enable_help[] = +"pipeline port in enable\n"; + +static void +cmd_pipeline_port_in_enable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "enable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); + return; + } + + status = pipeline_port_in_enable(pipeline_name, port_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_port_in_disable_help[] = +"pipeline port in disable\n"; + +static void +cmd_pipeline_port_in_disable(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + char *pipeline_name; + uint32_t port_id; + int status; + + if (n_tokens != 6) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "in") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); + return; + } + + if (parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "disable") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); + return; + } + + status = pipeline_port_in_disable(pipeline_name, port_id); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } +} + + +static const char cmd_pipeline_port_out_stats_help[] = +"pipeline port out stats read [clear]\n"; + +#define MSG_PIPELINE_PORT_OUT_STATS \ + "Pkts in: %" PRIu64 "\n" \ + "Pkts dropped by AH: %" PRIu64 "\n" \ + "Pkts dropped by other: %" PRIu64 "\n" + +static void +cmd_pipeline_port_out_stats(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_pipeline_port_out_stats stats; + char *pipeline_name; + uint32_t port_id; + int clear, status; + + if ((n_tokens != 7) && (n_tokens != 8)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "port") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (strcmp(tokens[3], "out") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); + return; + } + + if (parser_read_uint32(&port_id, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); + return; + } + + if (strcmp(tokens[5], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[6], "read") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); + return; + } + + clear = 0; + if (n_tokens == 8) { + if (strcmp(tokens[7], "clear") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "clear"); + return; + } + + clear = 1; + } + + status = pipeline_port_out_stats_read(pipeline_name, + port_id, + &stats, + clear); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } + + snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS, + stats.stats.n_pkts_in, + stats.n_pkts_dropped_by_ah, + stats.stats.n_pkts_drop); +} + + +static const char cmd_pipeline_table_stats_help[] = +"pipeline table stats read [clear]\n"; + +#define MSG_PIPELINE_TABLE_STATS \ + "Pkts in: %" PRIu64 "\n" \ + "Pkts in with lookup miss: %" PRIu64 "\n" \ + "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \ + "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \ + "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \ + "Pkts in with lookup miss dropped by others: %" PRIu64 "\n" + +static void +cmd_pipeline_table_stats(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size) +{ + struct rte_pipeline_table_stats stats; + char *pipeline_name; + uint32_t table_id; + int clear, status; + + if ((n_tokens != 6) && (n_tokens != 7)) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + pipeline_name = tokens[1]; + + if (strcmp(tokens[2], "table") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); + return; + } + + if (parser_read_uint32(&table_id, tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); + return; + } + + if (strcmp(tokens[4], "stats") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); + return; + } + + if (strcmp(tokens[5], "read") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); + return; + } + + clear = 0; + if (n_tokens == 7) { + if (strcmp(tokens[6], "clear") != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "clear"); + return; + } + + clear = 1; + } + + status = pipeline_table_stats_read(pipeline_name, + table_id, + &stats, + clear); + if (status) { + snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); + return; + } + + snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS, + stats.stats.n_pkts_in, + stats.stats.n_pkts_lookup_miss, + stats.n_pkts_dropped_by_lkp_hit_ah, + stats.n_pkts_dropped_lkp_hit, + stats.n_pkts_dropped_by_lkp_miss_ah, + stats.n_pkts_dropped_lkp_miss); +} + +/** + * ::= + * + * match + * acl + * priority + * ipv4 | ipv6 + * + * | array + * | hash + * raw + * | ipv4_5tuple + * | ipv6_5tuple + * | ipv4_addr + * | ipv6_addr + * | qinq + * | lpm + * ipv4 | ipv6 + */ +struct pkt_key_qinq { + uint16_t ethertype_svlan; + uint16_t svlan; + uint16_t ethertype_cvlan; + uint16_t cvlan; +} __attribute__((__packed__)); + +struct pkt_key_ipv4_5tuple { + uint8_t time_to_live; + uint8_t proto; + uint16_t hdr_checksum; + uint32_t sa; + uint32_t da; + uint16_t sp; + uint16_t dp; +} __attribute__((__packed__)); + +struct pkt_key_ipv6_5tuple { + uint16_t payload_length; + uint8_t proto; + uint8_t hop_limit; + uint8_t sa[16]; + uint8_t da[16]; + uint16_t sp; + uint16_t dp; +} __attribute__((__packed__)); + +struct pkt_key_ipv4_addr { + uint32_t addr; +} __attribute__((__packed__)); + +struct pkt_key_ipv6_addr { + uint8_t addr[16]; +} __attribute__((__packed__)); + +static uint32_t +parse_match(char **tokens, + uint32_t n_tokens, + char *out, + size_t out_size, + struct table_rule_match *m) +{ + memset(m, 0, sizeof(*m)); + + if (n_tokens < 2) + return 0; + + if (strcmp(tokens[0], "match") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); + return 0; + } + + if (strcmp(tokens[1], "acl") == 0) { + if (n_tokens < 14) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } + + m->match_type = TABLE_ACL; + + if (strcmp(tokens[2], "priority") != 0) { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); + return 0; + } + + if (parser_read_uint32(&m->match.acl.priority, + tokens[3]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "priority"); + return 0; + } + + if (strcmp(tokens[4], "ipv4") == 0) { + struct in_addr saddr, daddr; + + m->match.acl.ip_version = 1; + + if (parse_ipv4_addr(tokens[5], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr); + + if (parse_ipv4_addr(tokens[7], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr); + } else if (strcmp(tokens[4], "ipv6") == 0) { + struct in6_addr saddr, daddr; + + m->match.acl.ip_version = 0; + + if (parse_ipv6_addr(tokens[5], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16); + + if (parse_ipv6_addr(tokens[7], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16); + } else { + snprintf(out, out_size, MSG_ARG_NOT_FOUND, + "ipv4 or ipv6"); + return 0; + } + + if (parser_read_uint32(&m->match.acl.sa_depth, + tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth"); + return 0; + } + + if (parser_read_uint32(&m->match.acl.da_depth, + tokens[8]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da_depth"); + return 0; + } + + if (parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp0"); + return 0; + } + + if (parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp1"); + return 0; + } + + if (parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp0"); + return 0; + } + + if (parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp1"); + return 0; + } + + if (parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "proto"); + return 0; + } + + m->match.acl.proto_mask = 0xff; + + return 14; + } /* acl */ + + if (strcmp(tokens[1], "array") == 0) { + if (n_tokens < 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } + + m->match_type = TABLE_ARRAY; + + if (parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "pos"); + return 0; + } + + return 3; + } /* array */ + + if (strcmp(tokens[1], "hash") == 0) { + if (n_tokens < 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } + + m->match_type = TABLE_HASH; + + if (strcmp(tokens[2], "raw") == 0) { + uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX; + + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (parse_hex_string(tokens[3], + m->match.hash.key, &key_size) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "key"); + return 0; + } + + return 4; + } /* hash raw */ + + if (strcmp(tokens[2], "ipv4_5tuple") == 0) { + struct pkt_key_ipv4_5tuple *ipv4 = + (struct pkt_key_ipv4_5tuple *) m->match.hash.key; + struct in_addr saddr, daddr; + uint16_t sp, dp; + uint8_t proto; + + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (parse_ipv4_addr(tokens[3], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + + if (parse_ipv4_addr(tokens[4], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + + if (parser_read_uint16(&sp, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp"); + return 0; + } + + if (parser_read_uint16(&dp, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp"); + return 0; + } + + if (parser_read_uint8(&proto, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "proto"); + return 0; + } + + ipv4->sa = saddr.s_addr; + ipv4->da = daddr.s_addr; + ipv4->sp = rte_cpu_to_be_16(sp); + ipv4->dp = rte_cpu_to_be_16(dp); + ipv4->proto = proto; + + return 8; + } /* hash ipv4_5tuple */ + + if (strcmp(tokens[2], "ipv6_5tuple") == 0) { + struct pkt_key_ipv6_5tuple *ipv6 = + (struct pkt_key_ipv6_5tuple *) m->match.hash.key; + struct in6_addr saddr, daddr; + uint16_t sp, dp; + uint8_t proto; + + if (n_tokens < 8) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (parse_ipv6_addr(tokens[3], &saddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sa"); + return 0; + } + + if (parse_ipv6_addr(tokens[4], &daddr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "da"); + return 0; + } + + if (parser_read_uint16(&sp, tokens[5]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "sp"); + return 0; + } + + if (parser_read_uint16(&dp, tokens[6]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "dp"); + return 0; + } + + if (parser_read_uint8(&proto, tokens[7]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "proto"); + return 0; + } + + memcpy(ipv6->sa, saddr.s6_addr, 16); + memcpy(ipv6->da, daddr.s6_addr, 16); + ipv6->sp = rte_cpu_to_be_16(sp); + ipv6->dp = rte_cpu_to_be_16(dp); + ipv6->proto = proto; + + return 8; + } /* hash ipv6_5tuple */ + + if (strcmp(tokens[2], "ipv4_addr") == 0) { + struct pkt_key_ipv4_addr *ipv4_addr = + (struct pkt_key_ipv4_addr *) m->match.hash.key; + struct in_addr addr; + + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (parse_ipv4_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + ipv4_addr->addr = addr.s_addr; + + return 4; + } /* hash ipv4_addr */ + + if (strcmp(tokens[2], "ipv6_addr") == 0) { + struct pkt_key_ipv6_addr *ipv6_addr = + (struct pkt_key_ipv6_addr *) m->match.hash.key; + struct in6_addr addr; + + if (n_tokens < 4) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if (parse_ipv6_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + memcpy(ipv6_addr->addr, addr.s6_addr, 16); + + return 4; + } /* hash ipv6_5tuple */ + + if (strcmp(tokens[2], "qinq") == 0) { + struct pkt_key_qinq *qinq = + (struct pkt_key_qinq *) m->match.hash.key; + uint16_t svlan, cvlan; + + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, + tokens[0]); + return 0; + } + + if ((parser_read_uint16(&svlan, tokens[3]) != 0) || + (svlan > 0xFFF)) { + snprintf(out, out_size, MSG_ARG_INVALID, + "svlan"); + return 0; + } + + if ((parser_read_uint16(&cvlan, tokens[4]) != 0) || + (cvlan > 0xFFF)) { + snprintf(out, out_size, MSG_ARG_INVALID, + "cvlan"); + return 0; + } + + qinq->svlan = rte_cpu_to_be_16(svlan); + qinq->cvlan = rte_cpu_to_be_16(cvlan); + + return 5; + } /* hash qinq */ + + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } /* hash */ + + if (strcmp(tokens[1], "lpm") == 0) { + if (n_tokens < 5) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return 0; + } + + m->match_type = TABLE_LPM; + + if (strcmp(tokens[2], "ipv4") == 0) { + struct in_addr addr; + + m->match.lpm.ip_version = 1; + + if (parse_ipv4_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr); + } else if (strcmp(tokens[2], "ipv6") == 0) { + struct in6_addr addr; + + m->match.lpm.ip_version = 0; + + if (parse_ipv6_addr(tokens[3], &addr) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, + "addr"); + return 0; + } + + memcpy(m->match.lpm.ipv6, addr.s6_addr, 16); + } else { + snprintf(out, out_size, MSG_ARG_MISMATCH, + "ipv4 or ipv6"); + return 0; + } + + if (parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) { + snprintf(out, out_size, MSG_ARG_INVALID, "depth"); + return 0; + } + + return 5; + } /* lpm */ + + snprintf(out, out_size, MSG_ARG_MISMATCH, + "acl or array or hash or lpm"); + return 0; +} + +/** + * table_action ::= + * + * action + * fwd + * drop + * | port + * | meta + * | table + * [balance ... ] + * [meter + * tc0 meter policer g y r + * [tc1 meter policer g y r + * tc2 meter policer g y r + * tc3 meter policer g y r ]] + * [tm subport pipe ] + * [encap + * ether + * | vlan + * | qinq + * | mpls unicast | multicast + * + * label0